Question

This question about crossfading images already gave an answer to the crossfading solution in Canvas. I am trying to do the same thing, only difference is that i am trying to fade images that are loaded on runtime.

The images are loaded propperly but no fade is visible. Is this not working because of the loaded images? Thanks.

HTML

 <div id="wrapper">
     <canvas id="bg1"></canvas>
     <canvas id="bg2"></canvas>
 </div>

JS

var toggle = true;

var canvas         = document.getElementById('bg1');
    canvas.width   = $(document).width();
    canvas.height  = $(document).height();
var ctx            = canvas.getContext('2d');

var canvas2        = document.getElementById('bg2');
    canvas2.width  = $(document).width();
    canvas2.height = $(document).height();

var ctx2           = canvas2.getContext('2d');

var image = new Image();
image.src = 'download1.jpg';

var image2 = new Image();
image2.src = 'download2.jpg';

image.onload = function() {
    ctx.drawImage(image, 0, 0, 200, 100);
    ctx2.drawImage(image2, 0, 0, 200, 100);
};

$('#wrapper').click(function () {
    if (toggle)
    {
        $('#bg2').fadeIn();
        $('#bg1').fadeOut();
    }
    else
    {
        $('#bg1').fadeIn();
        $('#bg2').fadeOut();
    }

    toggle = !toggle;
});
Was it helpful?

Solution

Yep, you need to give your images time to load.

But also, jQuery cannot do fadeIn/fadeout on a canvas element so you will have to do that manually.

Demo: http://jsfiddle.net/m1erickson/zw9S4/

Code:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

$("#fade").hide();

var imageURLs=[];  // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-2.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-3.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-4.jpg");
loadAllImages();
//
function loadAllImages(){
    for (var i=0; i<imageURLs.length; i++) {
        var img = new Image();
        imgs.push(img);
        img.onload = function(){ 
            imagesOK++; 
            if (imagesOK>=imageURLs.length ) {
                $("#fade").show();
                ctx.drawImage(imgs[0],0,0);
            }
        };
        img.onerror=function(){alert("image load failed");} 
        img.crossOrigin="anonymous";
        img.src = imageURLs[i];
    }      
}


    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var fadeOutIndex=imgs.length-1;
    var fadeInIndex=0;
    var fadePct=0;

    function animateFade(){
        if(fadePct>100){return;}
        requestAnimationFrame(animateFade);
        ctx.clearRect(0,0,canvas.width,canvas.height);
        draw(imgs[fadeInIndex],fadePct/100);
        draw(imgs[fadeOutIndex],(1-fadePct/100));
        fadePct++;
    }

    function draw(img,opacity){
        ctx.save();
        ctx.globalAlpha=opacity;
        ctx.drawImage(img,0,0);
        ctx.restore();
    }

    $("#fade").click(function(){
        fadePct=0;
        if(++fadeOutIndex == imgs.length){fadeOutIndex=0;}
        if(++fadeInIndex == imgs.length){fadeInIndex=0;}
        animateFade();
    });

}); // end $(function(){});
</script>
</head>
<body>
    <button id="fade">Fade to next Image</button><br>
    <canvas id="canvas" width=204 height=204></canvas><br>
</body>
</html>

OTHER TIPS

Try to fade in/out the images directly on the canvas instead of fading in and out the canvas elements (or there is not really any point using the canvas as you could use image elements instead).

First, of course, wait for the images to load:

var isBusy = false,       /// for fade loop
    count = 2;            /// number of images to load
    image = new Image();
    image2 = new Image();

/// setup load handler
image.onload = image2.onload = handleLoad;
image.src = 'download1.jpg';
image2.src = 'download2.jpg';

function handleLoad() {
    count--;
    if (count === 0) {

        /// when loaded draw a single image onto canvas
        ctx.drawImage(image, 0, 0, ctx.canvas.width, ctx.canvas.height);
    }
};

Now we can change the click handler a little bit around and use canvas only to do the fade in of the next image:

$('#wrapper').click(function () {

    var img,         /// current image to fade in
        opacity = 0; /// current globalAlpha of canvas

    /// if we're in a fade exit until done    
    if (isBusy) return;
    isBusy = true;

    /// what image to use    
    img = toggle ? image2 : image;

    /// fade in
    (function fadeIn() {
        /// set alpha
        ctx.globalAlpha = opacity;

        /// draw image with current alpha
        ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);

        /// increase alpha to 1, then exit resetting isBusy flag
        opacity += 0.02;
        if (opacity < 1)
            requestAnimationFrame(fadeIn);
        else
            isBusy = false;
    })();

    toggle = !toggle;
});

Online demo

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top