gpt4 book ai didi

具有多个 setTimeout 的 JavaScript 动画

转载 作者:行者123 更新时间:2023-11-28 11:58:29 25 4
gpt4 key购买 nike

我正在尝试使用 setTimeout 为 3 个不同的形状设置动画,我的问题是如何使用多个 setTimeout 为 3 个不同的形状设置动画还有是否有更好的方法来做到这一点,也许使用 setInterval

window.onload = draw;
var x = 5;
var y = 5;

radius = 50;

var x2 = 50;
var y2 = 120;

var x3 = 53;
var y3 = 230;
var context;

var loopTimer;

function draw(){
var canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
context.save();
context.clearRect(0,0,720,550);

rectangle(x,y);
circle(x2,y2);
circle2(x3,y3);

}

function rectangle(x,y){
//drawing a rectangle
context.fillStyle = "rgba(93,119,188,237)";
context.clearRect(0,0,720,550);
context.rect(x, y, 50, 50);
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'yellow';
context.stroke();
x += 1;
loopTimer = setTimeout('rectangle('+x+','+y+')',50);
}

function circle(x2,y2){
//darwong a circle
context.beginPath();
context.clearRect(0,0,720,550);
context.fillStyle = "#0000ff";
//Draw a circle of radius 20 at the current coordinates on the canvas.
context.arc(x2, y2, radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
x2 += 1;
loopTimer = setTimeout('circle('+x2+','+y2+')',20);
}

function circle2(x3,y3){
//drawing a second circle
context.beginPath();
context.clearRect(0,0,720,550);
context.fillStyle = 'green';
context.arc(x3, y3, radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
context.lineWidth = 5;//border around the circle
context.strokeStyle = 'red';
context.stroke();
x3 += 1;
loopTimer = setTimeout('circle2('+x3+','+y3+')',20);
}

最佳答案

动画对象

制作数字动画时,永远不需要多个计时器。

关键是将属性绑定(bind)到动画对象,例如位置、速度(或步数)、颜色、形状等。

其逻辑步骤是创建自定义对象,我们可以收集这些信息并使用更新函数在循环内的单个步骤中为我们完成所有更新。

示例

<强> ONLINE DEMO HERE

让我们创建一个对象集合来存储所有对象:

var animObjects = [];

没什么特别的——只是一个数组。

单个循环

为了展示这有多简单,我将首先展示循环本身,然后剖析该对象。该循环只是迭代我们的集合并调用每个对象的 update 方法:

function loop() {

/// clear canvas before redrawing all objects
ctx.clearRect(0, 0, demo.width, demo.height);

/// loop through the object collection and update each object
for(var i = 0, animObject; animObject = animObjects[i]; i++) {
animObject.update();
}

/// use this instead of setTimeout/setInterval (!)
requestAnimationFrame(loop);
}

现在,您可能注意到我们在这里使用了 requestAnimationFrame (rAF),而不是 setTimeoutsetInterval。 rAF 允许我们同步到监视器的更新频率,而 setTimout/setInterval 则不能。此外,rAF 的工作效率比其他两个更高,如果我们需要制作大量动画,这将使我们受益匪浅。

动画对象

现在让我们看一下这个对象,为什么我们只需要调用 update 就可以动画化?

正如我们之前看到的,我们只需调用以下命令即可创建一个动画圆圈对象:

var animObject = new animCircle(context, x, y, radius, color, stepX, stepY);

这允许我们设置要使用的上下文(如果我们使用多层 Canvas )、起始位置、颜色和每帧的步数。请注意,这些属性可以在动画过程中更改(例如更改半径和颜色)。

对象本身看起来像这样 -

function animCircle(ctx, x, y, r, color, stepX, stepY) {

/// keep a reference to 'this' context for external calls
var me = this;

/// make the parameters public so we can alter them
this.x = x;
this.y = y;
this.radius = r;
this.color = color;
this.stepX = stepX;
this.stepY = stepY;

/// this will update the object by incrementing x and y
this.update = function() {

me.x += me.stepX;
me.y += me.stepY;

/// additional updates can be inserted here

render();
}

/// and this takes care of drawing the object with current settings
function render() {
ctx.beginPath();
ctx.arc(me.x, me.y, me.radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.fillStyle = me.color;
ctx.fill();
}
return this;
}

这就是全部内容!

对象 update() 方法将为我们完成所有计算,并调用内部 render() 方法。

您可以以不同的位置和速度创建许多这样的对象,并通过单个循环为所有这些对象设置动画。

为了简单起见,我只为圆圈创建了一个对象。您应该能够使用它作为基础来创建矩形对象以及您所拥有的对象。当然,您可以扩展对象以跟踪其他内容,例如描边颜色、 Angular 等。

为了演示,我还让对象从 Canvas 边缘反弹。请根据需要进行调整。

关于具有多个 setTimeout 的 JavaScript 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19071975/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com