绘制和重新绘制图像以模拟动画不起作用
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/
我有一个简单的动画显示煤气表从绿色变为红色。我只是在计时器上绘制、清除然后重新绘制图像以尝试模拟动画。虽然有点效果,但动画滞后,有时在本应完成后就来回走动。
代码如下:
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/