我正在尝试创建一个具有2个对象的画布动画:一个圆周和一个实心圆。我的目标是使圆周看起来代表圆轨道。但是,当尝试设置动画时,没有动画,只有当我单击以停止页面时,图像才会以圆圈在轨道中的随机位置出现(这意味着运动部件起作用)。 谢谢您的宝贵时间,代码如下:
function restartAnimate(){
runAnimation(0);
setTimeout(restartAnimate(),1000);
}
function runAnimation(i){
let animation = document.getElementById("Animation");
let anim = animation.getContext("2d");
anim.clearRect(0,0,300,150);
anim.save();
anim.strokeStyle = "#99ebff";
anim.lineWidth = 10;
anim.beginPath();
anim.arc(150, 75, 40, 0, 2 * Math.PI);
anim.stroke();
anim.restore();
anim.save()
anim.fillStyle = "#000000";
anim.translate(150,75);
anim.rotate(2 * Math.PI * i / 1000);
anim.translate(-150,-75);
anim.beginPath();
anim.arc(150 + 36.5, 75 ,13, 0, 2 * Math.PI);
anim.fill();
anim.restore();
i += 16;
if(i < 1000) setTimeout(runAnimation(i),16);
}
答案 0 :(得分:1)
您应使用requestAnimationFrame
进行动画处理,以使渲染结果与显示硬件刷新同步显示。
setTimeout
非常不准确,随着时间的流逝,您的功能将会落后。如果您使用requestAnimationFrame
,则可以使用第一个参数(以毫秒为单位的时间)来精确地保持时间。
ctx.save
和ctx.restore
可能是非常昂贵的通话,应尽可能避免。由于仅还原转换,因此可以根据需要使用ctx.setTransform()
无需重新启动动画,只需让其循环即可。
示例重写代码时要牢记以上几点和其他一些更改。有关更多信息,请参见代码注释。
// Define constants and query DOM outside animation functions
const canvas = document.getElementById("animCanvas");
const ctx = canvas.getContext("2d");
Math.PI2 = Math.PI * 2;
var startTime;
restartAnimate();
function restartAnimate() {
if (startTime === undefined) {
requestAnimationFrame(runAnimation);
} else {
startTime = 0; // next frame animation we have restarted
}
// setTimeout(restartAnimate(),1000); // No need to restart as angle is cyclic.
}
function runAnimation(time) {
if (!startTime) { startTime = time }
const currentTime = time - startTime;
ctx.setTransform(1,0,0,1,0,0); // resets transform, better than using save and restore
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); // avoid magic numbers
//ctx.save(); // not needed
ctx.setTransform(1,0,0,1,150, 75); // last two values set the origin
// and is the point we rotate around
ctx.strokeStyle = "#99ebff";
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(0, 0, 40, 0, Math.PI2); // rendering at the origin
ctx.stroke();
//ctx.restore(); // not needed
//ctx.save(); // not needed
ctx.fillStyle = "#000000";
//ctx.translate(150,75); // working from origin so don't need to translate
ctx.rotate(Math.PI2 * currentTime / 1000);
//ctx.translate(-150,-75); // working from origin so don't need to translate
ctx.beginPath();
ctx.arc(36.5, 0 ,13, 0, Math.PI2);
ctx.fill();
//ctx.restore(); not needed
requestAnimationFrame(runAnimation);
}
<canvas id="animCanvas"></canvas>