Fading a loaded image into Canvas with drawImage

让人想犯罪 __ 提交于 2019-12-11 04:17:18

问题


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;
});

回答1:


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>



回答2:


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.



来源:https://stackoverflow.com/questions/21537845/fading-a-loaded-image-into-canvas-with-drawimage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!