绘制并重新绘制图像以模拟动画是行不通的

Drawing and redrawing an image to simulate animation doesnt work

本文关键字:绘制 模拟 动画 行不通 新绘制 图像      更新时间:2023-09-26

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

这是代码:

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

    }

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

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

function meter(){
    requestAnimationFrame(meter);
    setTimeout(function() {
        //drawing stuff
    }, 2000);
    setTimeout(function() {
        //drawing stuff
    }, 2500);
    setTimeout(function() {
        //drawing stuff
    }, 3000);   
}

你用一个小改动就画了三次同样的东西。相反,把它变成一个带有参数的函数:

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

以下是正在运行的代码:http://jsfiddle.net/Niddro/7jxknwk4/