我有一个简单的动画,显示燃气表从绿色变为红色。我只是绘制,清除然后重新绘制计时器上的图像以尝试和模拟动画。虽然它很有效,但动画有所滞后,有时只是在应该完成后才会前后移动。
下面是代码:
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);
}
答案 0 :(得分:1)
在我看来,你有足够的时间来调用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);
以下是行动中代码的小提琴:http://jsfiddle.net/Niddro/7jxknwk4/