JS - 循环数组时的setInterval
JS - setInterval while looping for array
我有一个数组,其中填充了对象,这些对象拥有一个称为 "move" 或 "turn" 的属性,并指定如何在 canvas 上为图像设置动画。
单击按钮后,我想遍历数组并以正确的顺序为元素设置动画,即移动对象,转动它,再次移动它。
这是代码:
var animation = false;
this.executePlan = function(){ // part of object
var self = this // part of object
for (var i = 0; i < this.moves.length; i++){
var move = this.moves[i];
if (move.type == "move"){
var path = new Path({x: self.x, y: self.y}, {x: move.x, y: move.y});
animation = setInterval(function(){
console.log("move");
ctx.clearRect(0, 0, res, res);
self.draw();
self.x += path.vector.x;
self.y += path.vector.y;
path.vector.s--;
if (path.vector.s <= 0){
clearInterval(animation);
}
},
10);
}
else if (move.type == "turn"){
animation = setInterval(function(){
console.log("turn");
if (move.a > 0){
self.facing++;
move.a--;
}
else {
self.facing--;
move.a++;
}
ctx.clearRect(0, 0, res, res);
ctx.save();
ctx.translate(self.x, self.y);
ctx.rotate(self.facing*Math.PI/180);
ctx.drawImage(self.img, -self.size/2, -self.size/2, self.size, self.size);
ctx.restore();
if (move.a == 0){
clearInterval(animation);
}
},
30);
}
}
}
出于本示例的目的,我必须为直线运动路径设置动画,而不是转弯,而不是直线运动路径,并且我的印象是代码应该保持不变,即
第一个数组元素触发 if 子句,第二个触发 elseif 子句,第一个触发 if 子句。
然而,发生的情况是各种间隔确实重叠,这导致我的图像移出 canvas,同时一直旋转 - 而不是移动,然后旋转,最后再次直线移动
我该如何修复代码以及错误到底是什么?
谢谢,
问题是您同时启动了 both/all 个动画。
您需要一些机制来仅在较早的动画完成后才开始后续动画。我的建议是将您的 for 循环更改为一个函数,其中每个动画负责在其动画完成时再次调用该函数(增加 i
)。
编辑
我建议的方法示例(完全未经测试):
var animation = false;
this.executePlan = function() {
var self = this;
function doStep(i) {
var move = this.moves[i];
if (move.type == "move") {
var path = new Path({ x: self.x, y: self.y }, { x: move.x, y: move.y });
animation = setInterval(function() {
console.log("move");
ctx.clearRect(0, 0, res, res);
self.draw();
self.x += path.vector.x;
self.y += path.vector.y;
path.vector.s--;
if (path.vector.s <= 0) {
clearInterval(animation);
if (i + 1 < this.moves.length) {
doStep(i + 1); // if there's more, do the next step
}
}
}, 10);
}
else if (move.type == "turn") {
animation = setInterval(function() {
console.log("turn");
if (move.a > 0){
self.facing++;
move.a--;
}
else {
self.facing--;
move.a++;
}
ctx.clearRect(0, 0, res, res);
ctx.save();
ctx.translate(self.x, self.y);
ctx.rotate(self.facing*Math.PI/180);
ctx.drawImage(self.img, -self.size/2, -self.size/2, self.size, self.size);
ctx.restore();
if (move.a == 0) {
clearInterval(animation);
if (i + 1 < this.moves.length) {
doStep(i + 1); // if there's more, do the next step
}
}
}, 30);
}
}
doStep(0); // start the first animation
}
我有一个数组,其中填充了对象,这些对象拥有一个称为 "move" 或 "turn" 的属性,并指定如何在 canvas 上为图像设置动画。 单击按钮后,我想遍历数组并以正确的顺序为元素设置动画,即移动对象,转动它,再次移动它。
这是代码:
var animation = false;
this.executePlan = function(){ // part of object
var self = this // part of object
for (var i = 0; i < this.moves.length; i++){
var move = this.moves[i];
if (move.type == "move"){
var path = new Path({x: self.x, y: self.y}, {x: move.x, y: move.y});
animation = setInterval(function(){
console.log("move");
ctx.clearRect(0, 0, res, res);
self.draw();
self.x += path.vector.x;
self.y += path.vector.y;
path.vector.s--;
if (path.vector.s <= 0){
clearInterval(animation);
}
},
10);
}
else if (move.type == "turn"){
animation = setInterval(function(){
console.log("turn");
if (move.a > 0){
self.facing++;
move.a--;
}
else {
self.facing--;
move.a++;
}
ctx.clearRect(0, 0, res, res);
ctx.save();
ctx.translate(self.x, self.y);
ctx.rotate(self.facing*Math.PI/180);
ctx.drawImage(self.img, -self.size/2, -self.size/2, self.size, self.size);
ctx.restore();
if (move.a == 0){
clearInterval(animation);
}
},
30);
}
}
}
出于本示例的目的,我必须为直线运动路径设置动画,而不是转弯,而不是直线运动路径,并且我的印象是代码应该保持不变,即 第一个数组元素触发 if 子句,第二个触发 elseif 子句,第一个触发 if 子句。
然而,发生的情况是各种间隔确实重叠,这导致我的图像移出 canvas,同时一直旋转 - 而不是移动,然后旋转,最后再次直线移动
我该如何修复代码以及错误到底是什么?
谢谢,
问题是您同时启动了 both/all 个动画。
您需要一些机制来仅在较早的动画完成后才开始后续动画。我的建议是将您的 for 循环更改为一个函数,其中每个动画负责在其动画完成时再次调用该函数(增加 i
)。
编辑
我建议的方法示例(完全未经测试):
var animation = false;
this.executePlan = function() {
var self = this;
function doStep(i) {
var move = this.moves[i];
if (move.type == "move") {
var path = new Path({ x: self.x, y: self.y }, { x: move.x, y: move.y });
animation = setInterval(function() {
console.log("move");
ctx.clearRect(0, 0, res, res);
self.draw();
self.x += path.vector.x;
self.y += path.vector.y;
path.vector.s--;
if (path.vector.s <= 0) {
clearInterval(animation);
if (i + 1 < this.moves.length) {
doStep(i + 1); // if there's more, do the next step
}
}
}, 10);
}
else if (move.type == "turn") {
animation = setInterval(function() {
console.log("turn");
if (move.a > 0){
self.facing++;
move.a--;
}
else {
self.facing--;
move.a++;
}
ctx.clearRect(0, 0, res, res);
ctx.save();
ctx.translate(self.x, self.y);
ctx.rotate(self.facing*Math.PI/180);
ctx.drawImage(self.img, -self.size/2, -self.size/2, self.size, self.size);
ctx.restore();
if (move.a == 0) {
clearInterval(animation);
if (i + 1 < this.moves.length) {
doStep(i + 1); // if there's more, do the next step
}
}
}, 30);
}
}
doStep(0); // start the first animation
}