4

我正在循环播放一组动画帧中的一组图像。有 7 张图像,从 1-7 循环完成动画。我需要这个动画无限循环,但我想知道其中哪一个是最好的方法:

通过修改数组循环

/* Pull image from start of array. */
var image = frames.shift();
/* Process image. */
...
/* Add image back to end of array. */
frames.push(image );

使用计数器变量循环

/* Pull image by counter offset. */
var image = frames[counter];
/* Process image. */
...
/* Increment or reset counter value. */
counter + 1 === frames.length ? counter = 0 : counter = counter + 1;

我选择一个而不是另一个有什么原因吗?或者,有没有更好的方法来解决这个问题?

4

3 回答 3

5

修改数组将比简单地使用变量来跟踪您在数组中的位置更昂贵。更好的方法是,如果你无限循环,似乎只是使用一个while循环(而不是使用一个for你在里面重置计数器的循环):

var i = 0;
while (true) {
    doSomething to array[i];

    i = (i+1) % array.length;
}

但是,如果您的目标确实是每次经过给定的间隔时都无限期地进行动画,那么循环根本不理想。改为使用setInterval

var frames = ...; //your images
var i = 0;
function animate() {
    do something to frames[i];
    i = (i+1) % array.length;
}

setInterval(animate, time_between_runs);

wheretime_between_runs是在再次调用该函数之前应该经过多少时间。

于 2013-04-06T21:47:50.730 回答
2

一种可能性是放弃数组并使用链表。

使每一帧成为指向下一个对象的对象。然后最后一个指向第一个。然后你需要做的就是引用下一个对象。

var curr = first; // reference to first frame object

setInterval(function() {

    // process image
    curr.image.doSomething();

    // proceed to next
    curr = curr.next;

}, 1000);

没有计数器可以用这种方式搞砸。


设置链表通常非常简单,只需对设置数组的当前代码稍作修改即可完成。

var first = new Frame(); // This is your entry point
var current = first;        // This holds the current frame during setup

for (var i = 0; i < totalFrames; i++) {
    current.next = new Frame();   // Make the current reference a new frame
    current = current.next;          // Make the new frame current
}

current.next = first; // circular reference back to the first.

function Frame() {
    // set up this frame
}

然后first是你的起点。


或者链接可以在Frame构造函数中完成。

var first = new Frame(null); 
var current = first;

for (var i = 0; i < totalFrames; i++) {
    current = new Frame(current);
}

current.next = first;

function Frame(currFrame) {
    // link this frame to the given one
    if (currFrame)
        currFrame.next = this;

    // set up the rest of this frame
}
于 2013-04-06T22:04:15.757 回答
2

或者,我认为也可以使用循环链表。要将对象数组转换为循环链表:

frames.forEach(function(elem, index) { 
    elem.next = frames[index + 1] || frames[0];
});

现在您可以执行以下操作:

setInterval(function() {
    frame = frame.next;
    ....
}, delay);
于 2013-04-06T22:04:26.790 回答