绘制和重新绘制图像以模拟动画不起作用

Drawing and redrawing an image to simulate animation doesnt work

我有一个简单的动画显示煤气表从绿色变为红色。我只是在计时器上绘制、清除然后重新绘制图像以尝试模拟动画。虽然有点效果,但动画滞后,有时在本应完成后就来回走动。

代码如下:

function meter(){
        requestAnimationFrame(meter);

        setTimeout(function() {

        var radius = 40;
        ctx.clearRect(500, 200, 100, 100);
        ctx.beginPath();
        ctx.arc(550, 250, radius, 0, 2 * Math.PI, false);
        ctx.fillStyle = 'rgba(192, 192, 192, 0.4)';
        ctx.fill();
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#000000';
        ctx.stroke();

        ctx.fillStyle = "#ffcc4a";
        ctx.fillRect(525, 220, 50, 60);
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(528, 225, 44, 45);


        var grd = ctx.createLinearGradient(510, 0, 670, 0);
        grd.addColorStop(0, "black");
        grd.addColorStop(0.25, "yellow");
        grd.addColorStop(0.5, "red");
        ctx.fillStyle = grd;
        ctx.fillRect(530, 228, 40, 30);

            ctx.beginPath();
            ctx.fillStyle = "#000000";
            ctx.arc(550, 264, 5, 0, 2 * Math.PI, false);
            ctx.moveTo(549, 260);
            ctx.lineTo(548, 240);
            ctx.fill();
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#000000';
            ctx.stroke();
            ctx.closePath();


        ctx.closePath();
        //ctx.clearRect(500, 200, 100, 100);    

            }, 2000);

            setTimeout(function() {

        var radius = 40;
        ctx.clearRect(500, 200, 100, 100);
        ctx.beginPath();
        ctx.arc(550, 250, radius, 0, 2 * Math.PI, false);
        ctx.fillStyle = 'rgba(192, 192, 192, 0.4)';
        ctx.fill();
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#000000';
        ctx.stroke();

        ctx.fillStyle = "#ffcc4a";
        ctx.fillRect(525, 220, 50, 60);
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(528, 225, 44, 45);


        var grd = ctx.createLinearGradient(510, 0, 670, 0);
        grd.addColorStop(0, "black");
        grd.addColorStop(0.25, "yellow");
        grd.addColorStop(0.5, "red");
        ctx.fillStyle = grd;
        ctx.fillRect(530, 228, 40, 30);

            ctx.beginPath();
            ctx.fillStyle = "#000000";
            ctx.arc(550, 264, 5, 0, 2 * Math.PI, false);
            ctx.moveTo(549, 260);
            ctx.lineTo(558, 240);
            ctx.fill();
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#000000';
            ctx.stroke();
            ctx.closePath();


        ctx.closePath();
        //ctx.clearRect(500, 200, 100, 100);    

            }, 2500);

            setTimeout(function() {

        var radius = 40;
        ctx.clearRect(500, 200, 100, 100);
        ctx.beginPath();
        ctx.arc(550, 250, radius, 0, 2 * Math.PI, false);
        ctx.fillStyle = 'rgba(192, 192, 192, 0.4)';
        ctx.fill();
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#000000';
        ctx.stroke();

        ctx.fillStyle = "#ffcc4a";
        ctx.fillRect(525, 220, 50, 60);
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(528, 225, 44, 45);


        var grd = ctx.createLinearGradient(510, 0, 670, 0);
        grd.addColorStop(0, "black");
        grd.addColorStop(0.25, "yellow");
        grd.addColorStop(0.5, "red");
        ctx.fillStyle = grd;
        ctx.fillRect(530, 228, 40, 30);

            ctx.beginPath();
            ctx.fillStyle = "#000000";
            ctx.arc(550, 264, 5, 0, 2 * Math.PI, false);
            ctx.moveTo(549, 260);
            ctx.lineTo(568, 240);
            ctx.fill();
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#000000';
            ctx.stroke();
            ctx.closePath();


        ctx.closePath();
        //ctx.clearRect(500, 200, 100, 100);    

            }, 3000);   



    }

在我看来,您将有足够的时间多次调用 requestAnimationFrame 函数,而第一个 setTimeout 函数正在等待触发和绘制内容。这意味着您可能会在第一个触发之前启动 setTimeout 计时器数百次。

这基本上就是你所拥有的:

function meter(){
    requestAnimationFrame(meter);

    setTimeout(function() {
        //drawing stuff
    }, 2000);

    setTimeout(function() {
        //drawing stuff
    }, 2500);

    setTimeout(function() {
        //drawing stuff
    }, 3000);   
}

同一个东西你画了三遍,只做了一点小改动。相反,使用参数将其变成 1 个函数:

function meter(indicatorPosition){
    //black circle
    var radius = 40;
    ctx.clearRect(500, 200, 100, 100);
    ctx.beginPath();
    ctx.arc(550, 250, radius, 0, 2 * Math.PI, false);
    ctx.fillStyle = 'rgba(192, 192, 192, 0.4)';
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#000000';
    ctx.stroke();

    //yellow rectangle
    ctx.fillStyle = "#ffcc4a";
    ctx.fillRect(525, 220, 50, 60);
    //white rectangle over yellow
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(528, 225, 44, 45);

    //meter gradient background
    var grd = ctx.createLinearGradient(510, 0, 670, 0);
    grd.addColorStop(0, "black");
    grd.addColorStop(0.25, "yellow");
    grd.addColorStop(0.5, "red");
    ctx.fillStyle = grd;
    ctx.fillRect(530, 228, 40, 30);

    //circle and indicator
    ctx.beginPath();
    ctx.fillStyle = "#000000";
    ctx.arc(550, 264, 5, 0, 2 * Math.PI, false);
    ctx.moveTo(549, 260);
    ctx.lineTo(indicatorPosition, 240); //this is the only variable!
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#000000';
    ctx.stroke();
    ctx.closePath();
}

现在让它动起来:

如果你想让它每0.5秒移动一次,最好使用setInterval。

var meterPosition = 548 //your starting position
var myInterval = setInterval(function() {
    //each run we draw the meter
    meter(meterPosition);
    //Then we want to add 10 to the meter position
    meterPosition+=10;
    //We don't want the meter to go nuts and disappear to the right, so we'll make it reset after 3 moves
    if (meterPosition > 568) {
        meterPosition = 548;
    }
},500);

这里是一个 fiddle 代码的运行:http://jsfiddle.net/Niddro/7jxknwk4/