JS -在循环数组时设置interval

JS - setInterval while looping for array

本文关键字:设置 interval 数组 循环 JS      更新时间:2023-09-26

我有一个数组,它充满了拥有一个属性的对象,该属性被称为"move"或"turn",并指定如何在画布上动画图像。在点击一个按钮后,我想循环遍历数组并按正确的顺序为元素动画,即移动对象,转动它,再移动它。

这是代码:

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子句

然而,发生的事情是各种间隔确实重叠,这导致我的图像移动出画布,同时一直旋转-而不是移动,然后旋转,最后再次直线移动

我怎么能修复代码,到底是什么错误?

谢谢,

问题是你同时启动了两个/所有动画。

你需要一些机制来启动后续的动画,只有在之前的动画完成之后。我的建议是将你的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
}