【问题标题】:jQuery: Infinite loop alternate between 2 img srcjQuery:2个img src之间的无限循环交替
【发布时间】:2017-03-21 23:30:32
【问题描述】:

我正在尝试使用两个图像创建一个简单的 GIF 类动画。我想使用相同的 img 标签并在一个循环中更改 2 个 src 链接。

这是我目前所拥有的,但我不知道如何解决它:

HTML

<img class="logo" src="https://dl.dropbox.com/s/7mbi7un8i0sksoq/flaws1.svg" draggable="false">

jQuery

$(document).ready(function() {
    $(function(){
        setInterval(function(){
            setTimeout(function(){$('.logo').attr("src", "https://dl.dropbox.com/s/z4zb1ad94w92pra/flaws2.svg");}, 200);
            setTimeout(function(){$('.logo').attr("src", "https://dl.dropbox.com/s/7mbi7un8i0sksoq/flaws1.svg");}, 200);
        }, 400);
    });
});

简化的 CSS

body {
  background: black;
}

.logo {
    position: absolute;
    left: 0; right: 0; top: 0; bottom: 0; margin: auto;
    width: 70%;
}

【问题讨论】:

  • setInterval 中,从第一个setTimeout 中取出代码,使其立即运行。您已将它们安排在同一时间(大致)执行。
  • $(document).ready(function(...$(function(...同一件事。两者都不需要。
  • 我删除了第一个超时,它有点工作,除了它在大约 10-20 秒后开始,然后它正常工作。
  • 可能加载资源需要时间。不确定。

标签: javascript jquery settimeout setinterval infinite-loop


【解决方案1】:

我不明白您为什么需要 setIntervalsetTimeout。这工作得很好。 https://jsbin.com/zewudijara/edit?js,console,output

$(function(){
  var $logo = $('.logo');
  var index = 0;
  var sources = [
    'https://dl.dropbox.com/s/7mbi7un8i0sksoq/flaws1.svg',
    'https://dl.dropbox.com/s/z4zb1ad94w92pra/flaws2.svg',
  ];

  setInterval(function () {
    index ^= 1;
    $logo.attr('src', sources[index]);
  }, 400);
});

根据 @Brian 的出色反馈,我更新了我的答案,使用按位运算在 1 和 0 之间切换。

【讨论】:

  • 不错的解决方案,一个小问题是它最终会失败(在很长一段时间后),假设只有 2 张图像index ^= 1 进行切换可能会更安全,因为它只会切换无限期地介于 0 和 1 之间(通过按位异或),或者如果超过 2 个源,则如果 index &gt; source.length 包装为 0,则可以防止这种情况发生
【解决方案2】:

要将上面的 cmets 放入代码中,修复方法如下:

$(document).ready(function() {
    // Every 400 ms
    setInterval(function(){
        // Immediate
        $('.logo').attr("src", "https://dl.dropbox.com/s/z4zb1ad94w92pra/flaws2.svg");

        // In 200 ms
        setTimeout(function(){
          $('.logo').attr("src", "https://dl.dropbox.com/s/7mbi7un8i0sksoq/flaws1.svg");
        }, 200);
    }, 400);
});

您只希望通过setTimeout 延迟一个,而不是两者。


也就是说,既然它是一个切换,我可能会这样做:

$(document).ready(function() {
    var timer = 200
    setTimeout(function f(i){
        $('.logo').attr("src", "https://dl.dropbox.com/s/z4zb1ad94w92pra/flaws" + ((i%2)+1) + ".svg");
        setTimeout(f, timer, i+1);
    }, timer, 1);
});

当然不需要 jQuery:

document.addEventListener("DOMContentLoaded", function() {
  var timer = 200
  var logo = document.querySelector(".logo")
  setTimeout(function f(i) {
    logo.src = "https://dummyimage.com/240x180/0000fc/c4c4c4.gif&text=" + ((i % 2) + 1);
    setTimeout(f, timer, i + 1);
  }, timer, 1);
});
&lt;img class=logo src="https://dummyimage.com/240x180/0000fc/c4c4c4.gif&amp;text=1"&gt;

【讨论】:

  • 不错的解决方案,但需要注意的是,由于setTimeout 未将其他参数传递给回调,因此该解决方案在 IE i 得到太多,这最终将失败大的。如果在 2 个值之间切换,对按位异或的简单更改将允许它无限期地运行 setTimeout(f, timer, i ^ 1);
  • @Brian:关于旧版浏览器非常正确。绝对值得指出。我认为可以肯定地说i 永远不会变得太大。鉴于它每秒运行 5 次,并且在达到 Number.MAX_SAFE_INTEGER(即 9,007,199,254,740,991)之前不会出现问题,因此需要数百万年才能到达那里。 ;-) 不错的解决方案!
【解决方案3】:

我想我会分享我自己的方法。以上两个cmets都是正确的。本质上,问题是当您调用 setTimeout 时,函数调用是在 setTimeout 被调用时的 interval 毫秒内安排的,而不是从上一个设置的超时时间开始的 interval 毫秒。

现在,您只需从 setTimeout 调用中删除一个调用,您的代码即可工作。但是,以下代码也适用于您的目的,并避免您提到的延迟。

$(document).ready(function()
{
  setTimeout(setLogoA, 200);
}

var logo = $(".logo");
function setLogoA()
{
  logo.attr("src", "https://dl.dropbox.com/s/z4zb1ad94w92pra/flaws2.svg");
  setTimeout(setLogoB, 200);
}

function setLogoB()
{
  logo.attr("src", "https://dl.dropbox.com/s/7mbi7un8i0sksoq/flaws1.svg");
  setTimeout(setLogoA, 200);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多