gpt4 book ai didi

javascript - HTML Canvas : Animation Delay

转载 作者:行者123 更新时间:2023-12-02 13:48:01 26 4
gpt4 key购买 nike

Here是我的 Canvas 的演示。

Canvas 会生成一个随机矩形,并通过将其从 1.0 缩放到 1.2 并再次缩放回 1.0 来对其进行动画处理。 (有点像人的心脏)。该动画大约需要 2 秒才能完成。共有 60 次totalIterations。它从 0 开始,每帧递增 1,直到达到 60。一旦达到 60iteration 将设置回 0,并且动画从 1.2 缩小到 1.0.

我想要做的是在执行下一个周期之前(周期的意思是从1.0规模,到1.2,然后回到1.0 >),我想推迟规模。

这是我尝试做的:

上下文:

this.intermission = 3; // time to wait, or "defer" for
elapsed = (Date.now() - this.initTime) / 1000; // time elapsed since initialization (in seconds)

条件:

if((elapsed % this.intermission >= (this.intermission - (this.intermission-1))) && (elapsed % this.intermission <= (this.intermission + (this.intermission-1)))) {
ctx.scale(this.easing, this.easing);
}

条件解释(可能没有意义):

如果耗时除以 3 的余数大于或等于 2 并且耗时除以 3 的余数小于或等于 5,则使用缓动函数缩放矩形。

...我想给它一些“缓冲”空间来完成动画

如果我将中场休息时间增加到 10,上述条件将不再有效,因此我需要一个更好的解决方案。

我考虑过使用 setTimeout(function(){...}, x),但这是在 JavaScript 类内部。

最佳答案

动画列表/堆栈。

关键帧

最好的方法是设置代码来管理关键帧,这样您就可以为您希望随时间更改的对象的每个属性创建关键帧列表。这允许您创建非常复杂的动画,并可以序列化为 JSON 文件。这将动画与代码解耦,但需要更多代码。

动画列表

如果它只是一个简单的动画,那么您可以创建一个动画堆栈(如果动画顺序是静态的,则创建一个列表),它只是一组为动画的每个部分依次调用的函数。

您为动画的每个部分设置了一个startTime,请小心地设置一致,这样就不会出现任何时间漂移。如果动画周期长 4 秒,那么它应该每 4 秒重复一次,并且在 4,000,000 秒内它应该同样精确。

在为页面上的任何内容设置动画时,始终使用 requestAnimationFrame (rAF)。 rAF 调用回调函数,将时间(以毫秒为单位)(1/1000)作为第一个参数传递,精度为 1/1,000,000(0.001 毫秒)。

使用动画列表的无尽动画

const canvas = document.createElement("canvas");
canvas.height = canvas.width = 300;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas)

// ease function
function easeInOut(x, pow = 2) {
x = x < 0 ? 0: x > 1 ? 1 : x;
var xx = Math.pow(x,pow);
return xx/(xx+Math.pow(1-x,pow));
};
function MyObj(){
this.x = 100;
this.y = 100;
this.size = 40;
this.scale = 1;
}
MyObj.prototype = {
getUnitTime(duration){ // get the unit time
var unitTime = (globalTime - startTime) / duration;
if(unitTime >= 1){ // if over time
unitTime = 1; // make sure that the current frame is not over
startTime = startTime + duration; // next frame start (could be in the past)
currentAnim += 1; // next animation in the list
}
return unitTime;
},
grow(){
drawText("Grow 1s");
// grow for 1 second
this.scale = easeInOut(this.getUnitTime(1000)) * 0.6 + 1;
},
shrink(){
drawText("Shrink 1s");
// shrink for 1 second
this.scale = 1.6 - easeInOut(this.getUnitTime(1000)) * 0.6 ;
},
wait(){
drawText("Wait 2s");
this.getUnitTime(2000); // wait two seconds
},
draw(ctx){
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size * this.scale, 0, Math.PI * 2);
ctx.fill();
}
}

function drawText(text){
ctx.fillStyle = "black";
ctx.fillText(text,100,36);
}
var obj = new MyObj(); // create the object

// holds the animation list
const animationList = [
obj.grow.bind(obj), // bind the function calls to the object
obj.shrink.bind(obj),
obj.wait.bind(obj)
];

var currentAnim; // index of current animation
var startTime; // start time of current animation
var globalTime; // time from the requestAnimationFrame callback argument
ctx.font = "32px arial";
ctx.textAlign = "center";

// main animation loop
function update(time){
globalTime = time; // set the global
if(currentAnim === undefined){ // if not set then
startTime = time; // set start time
currentAnim = 0; // set the index of the first animation
}

// clear the screen
ctx.clearRect(0,0,canvas.width,canvas.height);

// call the animation function
animationList[currentAnim % animationList.length]();

// draw the object
obj.draw(ctx);

// request next frame
requestAnimationFrame(update);
}

// start it all happening
requestAnimationFrame(update);

堆栈

堆栈非常相似,但在动画有条件时使用。您使用一些事件将动画函数插入堆栈。然后根据需要从堆栈中移动动画函数。或者您可能希望动画重复 10 次,然后执行其他操作,然后重新开始。动画堆栈可以让您做到这一点,而不是有一个巨大的动画列表。

使用点击事件的堆栈示例。

const canvas = document.createElement("canvas");
canvas.height = canvas.width = 300;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas)

// ease function
function easeInOut(x, pow = 2) {
x = x < 0 ? 0: x > 1 ? 1 : x;
var xx = Math.pow(x,pow);
return xx/(xx+Math.pow(1-x,pow));
};
function MyObj(){
this.x = 100;
this.y = 100;
this.size = 40;
this.scale = 1;
}
MyObj.prototype = {
getUnitTime(duration){ // get the unit time
var unitTime = (globalTime - startTime) / duration;
if(unitTime >= 1){ // if over time
unitTime = 1; // make sure that the current frame is not over
startTime = startTime + duration; // next frame start (could be in the past)
currentAnim = undefined
}
return unitTime;
},
grow(){
drawText("Grow 1s");
// grow for 1 second
this.scale = easeInOut(this.getUnitTime(1000)) * 0.6 + 1;
},
shrink(){
drawText("Shrink 1s");
// shrink for 1 second
this.scale = 1.6 - easeInOut(this.getUnitTime(1000)) * 0.6 ;
},
timeup(){
drawText("Click to Animate");
currentAnim = undefined;

},
draw(ctx){
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size * this.scale, 0, Math.PI * 2);
ctx.fill();
}
}

function drawText(text){
ctx.fillStyle = "black";
ctx.fillText(text,100,36);
}
var obj = new MyObj(); // create the object

// holds the animation list
const animationStack = [obj.timeup.bind(obj)];

var currentAnim; // index of current animation
var startTime; // start time of current animation
var globalTime; // time from the requestAnimationFrame callback argument
ctx.font = "26px arial";
ctx.textAlign = "center";

function startAnim(){
animationStack.length = 0;
animationStack.push(obj.grow.bind(obj));
animationStack.push(obj.shrink.bind(obj));
animationStack.push(obj.timeup.bind(obj));
if(currentAnim === undefined){// only restart if animation is not running
requestAnimationFrame(update);
}
startTime = undefined;
currentAnim = undefined;
}
canvas.addEventListener("click",startAnim)

// main animation loop
function update(time){

globalTime = time; // set the global
if(startTime === undefined){ // if not set then
startTime = time; // set start time
}
if(currentAnim === undefined){
if(animationStack.length > 0){
currentAnim = animationStack.shift();
}
}

if(currentAnim === undefined){
return;
}

// clear the screen
ctx.clearRect(0,0,canvas.width,canvas.height);

// call the animation function
currentAnim();

// draw the object
obj.draw(ctx);

// request next frame

requestAnimationFrame(update);
}

// start it all happening
requestAnimationFrame(update);

关于javascript - HTML Canvas : Animation Delay,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41207837/

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