函数调用之间的javascript延迟数组中的每个索引 [英] javascript delay between function calls for each index in an array

查看:97
本文介绍了函数调用之间的javascript延迟数组中的每个索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  • 对数组中的每个元素执行逻辑。

  • 等待 X 下次执行之间的ms。

  • mouseover(#slider)暂停延迟 - 如果延迟= 1000毫秒,并且已经过了300毫秒, mouseout(#slider)将触发恢复倒计时剩余的700毫秒延迟。

  • 之后执行最后一个元素,循环返回再做一次 - 永远。

  • Execute logic on each element in array.
  • Wait X ms in between next execution.
  • mouseover(#slider) pauses delay - If delay = 1000ms, and 300ms had passed, mouseout(#slider) would trigger resume counting down the remaining 700ms delay.
  • After execution on last element, loop back to do it again - forever.

这是一个直观的解释:

var = s Array(1,2,3)

var x = s[1];   //get first element   
console.log(x); //do something to it
wait();         //START wait timer 1000ms

//------------> timer : 300ms
//------------> user  : mouseover (#slider) : pause timer
//------------> user  : waited 5000ms
//------------> user  : mouseout  (#slider) : resume timer
//------------> timer : 300ms --> still 700ms to go!
//------------> timer : 500ms
//------------> user  : mouseover (#slider) : pause timer
//------------> user  : waited 10000ms
//------------> user  : mouseout  (#slider) : resume timer
//------------> timer : 500ms --> still 500ms to go!

var x = s[2];   //get second element   
console.log(x); //do something to it
wait();         //START wait timer 1000ms

//------------> timer : 200ms
//------------> user  : mouseover (#slider) : pause timer
//------------> user  : onclick   (.slideButton1) : change index of array and clear timer
//------------> user  : waited 6000ms
//------------> user  : mouseout  (#slider) : resume timer
//------------> timer : 0ms --> still 1000ms to go!

var x = s[1];   //get first element   ( index was changed by clicking button )
console.log(x); //do something to it
wait();         //START wait timer 1000ms

// ... s[2] ... s[3] ...
//theres nothing else in the array, lets start back from s[1] again!



解决方案:



jQuery :

http:// jsfiddle .net / zGd8a / 8 /

此解决方案来自相关的 发表 。该插件的官方来源可以在 此处 中找到。

This solution came from a related post. The official source of this plugin can be found here.

原生JS:

http://jsfiddle.net/SyTFZ/4/

回答 Aadit M Shah 真的很有帮助。他还详细介绍了 Delta Timing 以及它在类似情况下的用途。

This Answer by Aadit M Shah was really helpful. He also goes into detail about Delta Timing and how it can be useful in similar cases.

提取其中任何一种方法以允许用于其他事情。

Abstract up either of these methods to allow use for other things.

推荐答案

好的,我不喜欢使用jquery并且很可能我不知道你想要实现什么。但是根据我的理解,我认为你应该这样做:

Okay, I don't use jquery and in all probability I have no clue as to what you're trying to achieve. However from what I understand I think you should do something like this:

var i = 0;
var t = this;

var timer = new DeltaTimer(function (time) {
    // your animation
    var x = t.s[i];
    x.delay("1000").css("background-color", "#FAAF16");
    delete t.s[i];
    t.s.push(x);
    // increment i
    i++;
}, 1000);

var start = timer.start();

你会注意到我使用了一个名为 DeltaTimer的构造函数。此构造函数在此 gist 中定义。它允许您使用 start stop 函数精确控制动画。传递的 render 函数给出 time 参数,该参数是 Date 。表达式 time - start 给出调用函数的确切时间(例如 4 1000 2000 ,...)。

You will notice here that I've used a constructor called DeltaTimer. This constructor is defined in this gist. It allows you to control your animations precisely using start and stop functions. The render function which is passed is given a time argument which is a Date. The expression time - start gives the exact time when the function was called (e.g. 4, 1000, 2000, ...).

使用<$的优势c $ c> DeltaTimer 超过 setTimeout setInterval 是:


  1. 纠正自己。这意味着动画更平滑且延迟更少。

  2. 可以通过启动和停止计时器来控制动画。

  3. 确切的时间函数调用传递给函数。这有助于跟踪正在渲染的帧,渲染精灵的位置等等。

  4. 动画的逻辑与时序控制的逻辑分开。因此代码更具凝聚力和更松散耦合。

  1. It corrects itself. This means that animations are smoother and there's less lag.
  2. The animation can be controlled by starting and stopping the timer.
  3. The exact time of the function call is passed to the function. This helps in keeping track of which frame is being rendered, where should the sprite be rendered, etc.
  4. The logic for animation is separated from the logic of timing control. Thus code is more cohesive and more loosely coupled.

您可以阅读关于增量计时的其他答案这里此处此处

You can read my other answers regarding delta timing here, here and here.

编辑1:这是其实非常简单。我们只是移出数组的第一个元素,处理它然后在最后将其推回。这是逻辑:

Edit 1: That's actually pretty simple. We simply shift out the first element of the array, process it and then push it back at the end. Here's the logic:

function loopIterate(array, callback, interval) {
    var timer = new DeltaTimer(function (time) {
        var element = array.shift();
        callback(element, time - start);
        array.push(element);
    }, interval);

    var start = timer.start();
};

现在我们可以创建一个数组并循环遍历它:

Now we can create an array and loop through it as follows:

var body = document.body;

loopIterate([1, 2, 3], function (element, time) {
    body.innerHTML += element + ": " + time + "<br/>";
}, 1000);

您可以在此处看到输出: http://jsfiddle.net/aGQfr/

You can see the output here: http://jsfiddle.net/aGQfr/

编辑2:哎呀,我发现了一个问题。根据我的理解,你希望在之后当前元素完成处理时,处理下一个元素。我的delta计时脚本不会这样做。它只以固定的时间间隔执行函数。

Edit 2: Oops, I found a problem. From what I understand you want to process the next element a certain amount of time after the current element is finished processing. My delta timing script doesn't do that. It only executes functions at fixed intervals of time.

因此,您根本不需要增量计时。您需要在处理完每个元素后调用 setTimeout

So, you don't need delta timing at all. You need to call setTimeout after each element has been processed:

function loopIterate(array, callback, interval) {
    var start = + new Date;
    process();

    function process() {
        var element = array.shift();
        callback(element, new Date - start);
        array.push(element);

        setTimeout(process, interval);
    }
};

之后只需创建一个数组并按如下方式循环:

After that just create an array and loop through it as follows:

loopIterate([1, 2, 3], function (element, time) {
    alert(element);
}, 1000);

您可以在此处查看演示(请注意您的浏览器可能不喜欢它): http://jsfiddle.net/aGQfr/1/

You can see the demo here (note that your browser may not like it): http://jsfiddle.net/aGQfr/1/

编辑3:您还可以合并方法一和二,以便您有一个脚本:

Edit 3: You may also combined methods one and two so that you have a script which:


  1. 在将下一个元素添加到事件队列之前等待处理完成。

  2. 可以使用 start 和<来控制code> stop function。

  3. 给出回调被调用的确切时间。

  4. 将处理与时间分开控制。

  1. Waits for the processing to finish before adding the next element to process to the event queue.
  2. Can be controlled using a start and stop function.
  3. Gives the exact time the callback is called.
  4. Separates processing from timing control.

我们将创建一个名为 LoopIterator 的构造函数,它返回一个迭代器对象,开始停止方法:

We'll create a constructor function called LoopIterator which returns an iterator object with start and stop methods:

function LoopIterator(array, callback, interval) {
    var start, iterate, timeout;

    this.start = function () {
        if (!iterate) {
            start = + new Date;
            iterate = true;
            loop();
        }
    };

    this.stop = function () {
        if (iterate) {
            clearTimeout(timeout);
            iterate = false;
        }
    };

    function loop() {
        var element = array.shift();
        callback(element, new Date - start);
        array.push(element);

        if (iterate) timeout = setTimeout(loop, interval);
    }
}

现在我们可以创建并启动一个新的迭代器,如下所示:

Now we can create and start a new iterator as follows:

var iterator = new LoopIterator([1, 2, 3], function (element, time) {
    alert(element);
}, 3000);

iterator.start();

如果你希望你甚至可以在鼠标移过一个元素或从一个元素移出时停止并启动迭代器元素分别为:

If you wish you may even stop and start the iterator when the mouse moves over an element or out of an element respectively:

var div = document.getElementsByTagName("div")[0];
div.addEventListener("mouseout", iterator.start, false);
div.addEventListener("mouseover", iterator.stop, false);

当停止时,迭代器的状态将被保留,当再次启动时,它将从它停止的位置继续。

When stopped the iterator's state is preserved and when started again it continues from where it left off.

您可以在此处看到演示: http://jsfiddle.net / PEcUG /

You may see the demo here: http://jsfiddle.net/PEcUG/

编辑4:所以你想创建一个简单的滑块?让我们从HTML开始,然后是CSS,然后是JavaScript。

Edit 4: So you want to create a simple slider? Let's start with the HTML, then the CSS and then the JavaScript.

HTML:

<div class="slider">
    <div class="slide">Slide 1</div>
    <div class="slide">Slide 2</div>
    <div class="slide">Slide 3</div>
</div>

我们有一个 div 元素和一个类名为的滑块(因为页面上可能有多个滑块)。每个滑块都有零个或多个 div 元素,类幻灯片。每张幻灯片可以包含任意内容。滑块也有按钮,但我们不在HTML中包含它,因为它将由JavaScript自动生成。没有冗余。另请注意,没有任何幻灯片是手动编号的。一切都由JavaScript处理。

We have a div element with a class called slider (because there may be more than one slider on the page). Each slider has zero or more div elements with the class slide. Each slide may have arbitrary content. The slider will also have buttons, but we don't include this in the HTML as it will be generated automatically by JavaScript. No redundancy. Also note that none of the slides are manually numbered. Everything is handled by JavaScript.

CSS:

.slide {
    background-color: #EEEEEE;
    -moz-border-radius: 0.25em;
    -webkit-border-radius: 0.25em;
    border-radius: 0.25em;
    display: none;
    padding: 1em;
}

.slider-button {
    background-color: #CCCCCC;
    -moz-border-radius: 0.25em;
    -webkit-border-radius: 0.25em;
    border-radius: 0.25em;
    cursor: pointer;
    float: right;
    height: 1.25em;
    margin: 0.5em;
    width: 1.25em;
}

您可以根据自己的喜好提供任意CSS。但重要的一点是 .slide 必须有 display:none; 因为最初必须隐藏幻灯片。另外 .slider-button 必须有 float:right; 。这很重要,因为向右浮动的元素的顺序可以颠倒。因此,第一个按钮实际上是最后一个按钮。这必须由JavaScript正确处理,因此除非您知道自己在做什么,否则不要更改它。

You may supply arbitrary CSS to suit your taste. An important point however is that .slide must have display: none; because the slides must initially be hidden. Also .slider-button must have float: right;. This is important as elements floated to the right have their order reversed. Thus the first button is actually the last button. This must be handled correctly by JavaScript so don't change it unless you know what you're doing.

JavaScript:

好的,我会自下而上解释:

Alright, I'll explain this bottom up:

window.addEventListener("DOMContentLoaded", function () {
    var sliders = document.querySelectorAll(".slider");
    var length = sliders.length;

    for (var i = 0; i < length; i++)
        new Slider(sliders[i], 2000);
}, false);

这里 Slider 是一个初始化的构造函数并启动它传递的滑块元素。它接受两个幻灯片之间的时间间隔作为第二个参数。这是 Slider的代码

Here Slider is a constructor function which initializes and starts the slider element it passed. It accepts the time interval between two slides as the second argument. Here's the code for Slider:

function Slider(slider, interval) {
    var slides = slider.querySelectorAll(".slide");
    var iterate, start, timeout, delay = interval;
    slides = Array.prototype.slice.call(slides);
    var buttons = [], numbers = [], goto = [];
    var length = slides.length;

    for (var i = 0; i < length; i++) {
        var button = document.createElement("div");
        button.setAttribute("class", "slider-button");
        slider.appendChild(button);
        buttons.unshift(button);
        numbers.push(i + 1);

        var handler = getHandler(length - i);
        button.addEventListener("click", handler, false);
        goto.unshift(handler);
    }

    this.goto = function (index) {
        var gotoSlide = goto[index];
        if (typeof gotoSlide === "function")
            gotoSlide();
    };

    slider.addEventListener("mouseover", stop, false);
    slider.addEventListener("mouseout", start, false);

    this.start = start;
    this.stop = stop;

    showSlide();
    start();

    function start() {
        if (!iterate) {
            iterate = true;
            start = + new Date;
            timeout = setTimeout(loop, delay);
        }
    }

    function stop() {
        if (iterate) {
            iterate = false;
            clearTimeout(timeout);
            delay = interval - new Date + start;
        }
    }

    function loop() {
        hideSlide();
        slideSlider();
        showSlide();

        if (iterate) {
            start = + new Date;
            timeout = setTimeout(loop, interval);
        }
    }

    function hideSlide() {
        slides[0].style.display = "none";
        buttons[0].style.backgroundColor = "#CCCCCC";
    }

    function slideSlider() {
        slides.push(slides.shift());
        buttons.push(buttons.shift());
        numbers.push(numbers.shift());
    }

    function showSlide() {
        slides[0].style.display = "block";
        buttons[0].style.backgroundColor = "#FAAF16";
    }

    function getHandler(number) {
        return function () {
            hideSlide();
            while (numbers[0] !== number) slideSlider();
            showSlide();
        };
    }
}

代码非常明显。每个 Slider 的实例都有一个 start stop goto 更精细控制的方法。 goto 方法采用幻灯片索引号。对于 n 幻灯片的索引范围从 0 n - 1 。就是这样。

The code is pretty self-explanatory. Every instance of Slider has a start, stop and goto method for finer control. The goto method takes a slide index number. For n slides the indices range from 0 to n - 1. That's it.

滑块的演示在这里: http://jsfiddle.net/SyTFZ/4/

这篇关于函数调用之间的javascript延迟数组中的每个索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆