为什么我添加了计数器变量和间隔之后我的动画不工作了?
Why is my animation not working now that I've added counter variable and Intervals?
我在 class 中有一个动画功能。
动画是一棵树 'shuddering' 沿着 x 轴快速来回移动,就像被斧头砍中一样。
我希望发生的事情:
当我单击树时,动画应该开始、停止、开始、停止、开始然后永久停止。在我看来,动画 运行 和停止的比例大约是 2s 运行,8s 停止。动画所停留的边界非常小(见最后的 if 语句),速度为 4。因此树在两者之间弹跳得非常快,给人一种 'shudder' 的印象。
该函数在函数 setup() 中调用的 class 中。 tree.shudder() 但是在循环函数 draw() 中被调用。
这是一个 iteration/cycle 工作动画的代码:
shudder() {
let d = dist(mouseX, mouseY, this.x, this.y);
let speed = 0;
if (d < 50) {
speed = 4;
if (this.x < this.l || this.x > this.r) {
speed = speed * -1;
}
} else {
speed = 0;
}
this.x = this.x + speed;
}
动画一直有效,直到我尝试自动启动和停止抖动。
当我添加计数器变量和 setInterval/clearInterval 函数时,抖动不再起作用。
我正在使用 p5 库。
谁能看出为什么我的动画在这里停止工作?
function setup() {
createCanvas(windowWidth, windowHeight);
trees = new Trees(200, 200);
}
function draw() {
trees.shudder();
}
shudder() {
let d = dist(mouseX, mouseY, this.x, this.y);
let counter = 0;
let speed = 0;
if (d < 50) {
let interval = setInterval(() => {
speed = 4;
counter++;
console.log(counter);
if (this.x < this.l || this.x > this.r) {
speed = speed * -1;
}
if (counter === 3) {
clearInterval(interval)
}
}, 1000)
} else {
speed = 0;
}
this.x = this.x + speed;
}
在 console.log 中,如果我单击树并让 60 帧过去,就会发生这种情况:
60trees.js:31 1
trees.js:31 2
trees.js:31 1
trees.js:31 2
2trees.js:31 1
2trees.js:31 2
并无限运行...
但是,如果我在树上单击并在 60 帧通过之前单击关闭,我会得到我想要的:
26trees.js:31 1
26trees.js:31 2
26trees.js:31 3
任何帮助将不胜感激!
一些问题:
setInterval
在d < 50
时执行,也就是说会连续执行几次,而不考虑已经执行过。所以你会得到一堆大约同时到期的计时器。
您在 setInterval
回调中修改的 counter
和 speed
引用调用 setInterval
时的变量,并且对 shudder
的后续调用没有影响,其中这些变量是新变量实例。
你每秒只检查一次,看this.x
是否还在范围内。这最好在动画期间的每一帧完成。
在为每一帧调用的函数中使用 setInterval
看起来很糟糕。它可以工作,但你需要非常小心地做事。
我会选择一种模式,您可以计算动画的结束时间,然后只读出当前时间,看看您是否已经到了。还要确保保持有关速度等的状态(在 this
中)...
像这样:
shudder() {
if (!this.steps) { // not yet (ever) animated?
this.speed = 0;
let d = dist(mouseX, mouseY, this.x, this.y);
if (d < 50) {
// Adapt these numbers to set the time at which animation should pause/restart:
this.steps = [0, 500, 1000, 1500, 2000, 2500].map(i => Date.now() + i);
}
} else if (this.steps[0] < Date.now()) { // duration completed?
this.speed = 4 - Math.abs(this.speed); // Toggle between animate and pause
this.steps.shift(); // Remove a step, since that duration has completed
}
if (this.x < this.l || this.x > this.r) this.speed = -this.speed;
this.x += this.speed;
}
我在 class 中有一个动画功能。
动画是一棵树 'shuddering' 沿着 x 轴快速来回移动,就像被斧头砍中一样。
我希望发生的事情:
当我单击树时,动画应该开始、停止、开始、停止、开始然后永久停止。在我看来,动画 运行 和停止的比例大约是 2s 运行,8s 停止。动画所停留的边界非常小(见最后的 if 语句),速度为 4。因此树在两者之间弹跳得非常快,给人一种 'shudder' 的印象。
该函数在函数 setup() 中调用的 class 中。 tree.shudder() 但是在循环函数 draw() 中被调用。
这是一个 iteration/cycle 工作动画的代码:
shudder() {
let d = dist(mouseX, mouseY, this.x, this.y);
let speed = 0;
if (d < 50) {
speed = 4;
if (this.x < this.l || this.x > this.r) {
speed = speed * -1;
}
} else {
speed = 0;
}
this.x = this.x + speed;
}
动画一直有效,直到我尝试自动启动和停止抖动。 当我添加计数器变量和 setInterval/clearInterval 函数时,抖动不再起作用。
我正在使用 p5 库。
谁能看出为什么我的动画在这里停止工作?
function setup() {
createCanvas(windowWidth, windowHeight);
trees = new Trees(200, 200);
}
function draw() {
trees.shudder();
}
shudder() {
let d = dist(mouseX, mouseY, this.x, this.y);
let counter = 0;
let speed = 0;
if (d < 50) {
let interval = setInterval(() => {
speed = 4;
counter++;
console.log(counter);
if (this.x < this.l || this.x > this.r) {
speed = speed * -1;
}
if (counter === 3) {
clearInterval(interval)
}
}, 1000)
} else {
speed = 0;
}
this.x = this.x + speed;
}
在 console.log 中,如果我单击树并让 60 帧过去,就会发生这种情况:
60trees.js:31 1
trees.js:31 2
trees.js:31 1
trees.js:31 2
2trees.js:31 1
2trees.js:31 2
并无限运行...
但是,如果我在树上单击并在 60 帧通过之前单击关闭,我会得到我想要的:
26trees.js:31 1
26trees.js:31 2
26trees.js:31 3
任何帮助将不胜感激!
一些问题:
setInterval
在d < 50
时执行,也就是说会连续执行几次,而不考虑已经执行过。所以你会得到一堆大约同时到期的计时器。您在
setInterval
回调中修改的counter
和speed
引用调用setInterval
时的变量,并且对shudder
的后续调用没有影响,其中这些变量是新变量实例。你每秒只检查一次,看
this.x
是否还在范围内。这最好在动画期间的每一帧完成。在为每一帧调用的函数中使用
setInterval
看起来很糟糕。它可以工作,但你需要非常小心地做事。
我会选择一种模式,您可以计算动画的结束时间,然后只读出当前时间,看看您是否已经到了。还要确保保持有关速度等的状态(在 this
中)...
像这样:
shudder() {
if (!this.steps) { // not yet (ever) animated?
this.speed = 0;
let d = dist(mouseX, mouseY, this.x, this.y);
if (d < 50) {
// Adapt these numbers to set the time at which animation should pause/restart:
this.steps = [0, 500, 1000, 1500, 2000, 2500].map(i => Date.now() + i);
}
} else if (this.steps[0] < Date.now()) { // duration completed?
this.speed = 4 - Math.abs(this.speed); // Toggle between animate and pause
this.steps.shift(); // Remove a step, since that duration has completed
}
if (this.x < this.l || this.x > this.r) this.speed = -this.speed;
this.x += this.speed;
}