setTimeout 通过多个选项卡加快速度

发布于 2024-11-09 07:18:22 字数 1405 浏览 3 评论 0原文

我遇到类似于 这个。但该解决方案对我没有帮助,因为我无法在文件中使用 php。

我的网站有一个滑块,其中包含每 8 秒移动一次的图像列表。但是,当我在浏览器中打开几个选项卡然后再次切换回来时,它就变得疯狂了。 滑块立即将图像一张一张地移动,没有 8 秒的时间延迟。

我只在 Chrome 和最新的 Firefox 中看到它。

**编辑:我检查了console.log(),setTimeout在clearTimeout之前和之后返回相同的数字。不知道为什么。也许这也有关系? **

编辑2:我添加了一个小提琴:http://jsfiddle.net/Rembrand/ qHGAq/8/

代码如下所示:

spotlight: {
    i: 0,
   timeOutSpotlight: null,

   init: function()
   {
       $('#spotlight .controls a').click(function(e) {

           // do stuff here to count and move images

           // Don't follow the link
           e.preventDefault();

           // Clear timeout
           clearTimeout(spotlight.timeOutSpotlight);

           // Some stuff here to calculate next item

           // Call next spotlight in 8 seconds
           spotlight.timeOutSpotlight = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);
       });

       // Select first item
       $('#spotlight .controls a.next:first').trigger('click');
   },

   animate: function(i)
   {
       $('#spotlight .controls li:eq(' + (spotlight.i) + ') a.next').trigger('click');
   }
}

I’m having a setTimeout problem similar to this one. But that solution doesn't help me since I can’t use php in my file.

My site has a slider with a list of images that move every 8 seconds.However, when I have opened a few tabs in the browser and then switch back again, it goes nuts.
The slider proceeds to move the images one after the other immediately without the 8 second timedelay.

I'm only seeing it in Chrome and the latest Firefox.

**EDIT: I checked with console.log() and the setTimeout returns the same number before and after the clearTimeout. Not sure why. Maybe that also has something to do with it? **

EDIT 2: I added a fiddle: http://jsfiddle.net/Rembrand/qHGAq/8/

The code looks something like:

spotlight: {
    i: 0,
   timeOutSpotlight: null,

   init: function()
   {
       $('#spotlight .controls a').click(function(e) {

           // do stuff here to count and move images

           // Don't follow the link
           e.preventDefault();

           // Clear timeout
           clearTimeout(spotlight.timeOutSpotlight);

           // Some stuff here to calculate next item

           // Call next spotlight in 8 seconds
           spotlight.timeOutSpotlight = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);
       });

       // Select first item
       $('#spotlight .controls a.next:first').trigger('click');
   },

   animate: function(i)
   {
       $('#spotlight .controls li:eq(' + (spotlight.i) + ') a.next').trigger('click');
   }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

墨落画卷 2024-11-16 07:18:22

来自 jQuery 文档

由于 requestAnimationFrame() 的性质,您永远不应该
使用 setInterval 或 setTimeout 循环对动画进行队列。为了
保留CPU资源,支持requestAnimationFrame的浏览器
当窗口/选项卡未显示时,不会更新动画。如果
您继续通过 setInterval 或 setTimeout 对动画进行排队,同时
动画暂停,所有排队的动画将开始播放
当窗口/选项卡重新获得焦点时。为了避免这个潜在的问题,
在循环中使用最后一个动画的回调,或者附加一个
函数到 elements.queue()
来设置开始下一个的超时
动画。

From the jQuery documentation:

Because of the nature of requestAnimationFrame(), you should never
queue animations using a setInterval or setTimeout loop. In order to
preserve CPU resources, browsers that support requestAnimationFrame
will not update animations when the window/tab is not displayed. If
you continue to queue animations via setInterval or setTimeout while
animation is paused, all of the queued animations will begin playing
when the window/tab regains focus. To avoid this potential problem,
use the callback of your last animation in the loop, or append a
function to the elements .queue()
to set the timeout to start the next
animation.

花想c 2024-11-16 07:18:22

我终于找到了答案,但这根本不是我所期待的。
罪魁祸首似乎是 jQuery 的 .animate(),我用它来移动滑块中的图像。

我用这个计算和移动我的图像位置:

$('.spotlight-inner')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
 ;

现在的问题似乎是,在某些浏览器中,在切换到新选项卡并返回后,jQuery 的 .animate() 会保存动画并立即将它们全部触发。所以我添加了一个过滤器来防止排队。该解决方案来自 CSS-Tricks.com

$('.spotlight-inner')
    .filter(':not(:animated)')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
;

返回时看到的第一张幻灯片可以表现有点紧张,但比以前的超高速旋转木马要好。

此处修改完整代码

I finally found my answer and it’s not at all what I was expecting.
It seems the culprit is jQuery’s .animate(), which I use to move the images in the slider.

I calculate and move my images positions with this:

$('.spotlight-inner')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
 ;

Now the problem seems to be that in some browsers, after you switch to a new tab and back, jQuery’s .animate() saves up the animations and fires them all at once. So I added a filter to prevent queueing. That solutions comes from CSS-Tricks.com :

$('.spotlight-inner')
    .filter(':not(:animated)')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
;

The first slide you see when you go back can act a little jumpy but it’s better than the superspeed carousel from before.

Fiddle with the full code here

小兔几 2024-11-16 07:18:22

使用 jquery animate 队列属性有一种更简单的方法:

$(this).animate({
    left: '+=100'
}, {duration:500, queue:false});

There is an easier way using the jquery animate queue property:

$(this).animate({
    left: '+=100'
}, {duration:500, queue:false});
迷爱 2024-11-16 07:18:22

我不知道这是否对您有帮助,但它对我的幻灯片很有帮助。我所做的是,每次我调用一个由于 setTimeout 而应该在设定的时间间隔发生的动画时,我都会调用clearQueue(),这将消除已设置为发生的任何其他动画。然后我会调用动画。这样,当您返回该选项卡时,您就不会看到所有这些动画都排队,并且会变得疯狂。您最多只能设置一项。

所以像这样的事情:

       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.clearQueue(); // get rid of other instances of the animation
            spotlight.animate(spotlight.i);
        }, 8000);

它可能不适用于所有情况(取决于时间),但我希望这对某人有帮助!

I don't know if this will help you, but it helped me with my slideshow. What I did was everytime I called an animation that was supposed to happen at a set interval because of the setTimeout, I called clearQueue() which would get rid of any other animations that had been set to happen. then i'd call the animation. That way when you come back to that tab, you don't have all these animations queued up and it goes crazy. at max you'll only have one set up.

So something like this:

       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.clearQueue(); // get rid of other instances of the animation
            spotlight.animate(spotlight.i);
        }, 8000);

It may not work in all cases (depending on timing), but I hope that helps somebody!

书信已泛黄 2024-11-16 07:18:22

您还必须认为您使用了clearTimeout。

当您调用 setTimeout 函数时,它会返回一个 ID,您可以将此 ID 保存在变量中,例如

timeoutID = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);

,在设置新超时之前,您可以调用该函数,例如

clearTimeout(timeoutID)

You must also think you use clearTimeout.

As you call setTimeout function it returns an ID you can save this ID in a variable like

timeoutID = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);

and before setting a new timeout you can call the function like

clearTimeout(timeoutID)
回眸一遍 2024-11-16 07:18:22

我怀疑浏览器会将“单击”等输入事件排队,但仅在事件发生的选项卡实际具有焦点时才触发它们。

也许您应该尝试直接调用点击回调,而不是使用 trigger('click')

像这样的东西:

spotlight: {
    i: 0,
   timeOutSpotlight: null,
   clickFunc: function(element) {

       // do stuff here to count and move images

       // Clear timeout
       clearTimeout(spotlight.timeOutSpotlight);

       // Some stuff here to calculate next item

       // Call next spotlight in 8 seconds
       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.animate(spotlight.i);
       }, 8000);
   },

   init: function()
   {

       $('#spotlight .controls a').click(function (e) {

           // Don't follow the link
           e.preventDefault();

           spotlight.clickFunc(this);
       });

       // Select first item
       spotlight.clickFunc($('#spotlight .controls a.next:first'));
   },

   animate: function(i)
   {
       var element = $('#spotlight .controls li:eq('+spotlight.i+') a.next');
       spotlight.clickFunc(element);
   }
}

My suspicion is that the browser queues input events like 'click' but only fires them when the tab where the event occurs actually has focus.

Perhaps you should try calling your click callbacks directly instead of using trigger('click').

Something like this:

spotlight: {
    i: 0,
   timeOutSpotlight: null,
   clickFunc: function(element) {

       // do stuff here to count and move images

       // Clear timeout
       clearTimeout(spotlight.timeOutSpotlight);

       // Some stuff here to calculate next item

       // Call next spotlight in 8 seconds
       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.animate(spotlight.i);
       }, 8000);
   },

   init: function()
   {

       $('#spotlight .controls a').click(function (e) {

           // Don't follow the link
           e.preventDefault();

           spotlight.clickFunc(this);
       });

       // Select first item
       spotlight.clickFunc($('#spotlight .controls a.next:first'));
   },

   animate: function(i)
   {
       var element = $('#spotlight .controls li:eq('+spotlight.i+') a.next');
       spotlight.clickFunc(element);
   }
}
唠甜嗑 2024-11-16 07:18:22

您运行的是哪个版本的 jQuery?显然这个问题在 1.6.3 版本中已经“修复”了——他们恢复了导致这种情况发生的更改。讨论此处此处

尽管这个问题将来可能必须得到解决,但目前看来我们已经摆脱了困境。

What version of jQuery are you running? Apparently this problem was 'fixed' for version 1.6.3 - they reverted the change that caused this to happen. Discussions here and here.

Though this issue will likely have to be addressed in the future, it seems as though we're off the hook for now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文