【问题标题】:Javascript – Switching between images with varying intervalsJavascript – 在不同间隔的图像之间切换
【发布时间】:2014-09-26 15:58:24
【问题描述】:

我想在初始延迟后以两个不同的时间间隔在两个 png 图像之间自动切换:

  1. 图像 A 显示 2 秒(初始延迟)
  2. 图像 B 显示 0.3 秒
  3. 图像 A 显示 6 秒
  4. 从第 2 步开始重复

我发现问题 Javascript - Switching Between Two Imagesletiagoalves’ 教学代码,展示了如何在两个图像之间交替显示两个图像相同的时间量:

<img id="Change_Image" src="http://placehold.it/200x200" alt="Letter A">

function change_image() {
    var url = document.getElementById('Change_Image').src;
    if (url == 'http://placehold.it/200x200') {
        document.getElementById('Change_Image').src = 'http://placehold.it/100x100';
    } else {
        document.getElementById('Change_Image').src = 'http://placehold.it/200x200';
    }
}

setInterval(change_image, 2000);

(Working demo at jsfiddle)

...并尝试通过使用setInterval()setTimeout 的各种组合对其进行修改,以在不同时间显示图像,但到目前为止无济于事:

  1. 使用一个setTimeout() 和两个setInterval()
    • 这里的想法是首先显示图像 A,start_animation() 使用 setTimeout() 等待 2 秒,然后再调用 change_image() 显示图像 B。与此同时,change_back() 是每 0.3 秒调用一次,因此图像 B 的显示时间永远不会超过 0.3 秒,change_image() 每 6 秒调用一次,因此图像 B 每 6 秒显示一次。
    • 结果 – 图像切换,但间隔有点不确定: 有时图像 B 显示的时间大约是预期时间,有时它会非常短暂地闪烁过去。我想这是因为change_image()change_back() 同时执行时的干扰模式。

代码:

function start_animation() {
        change_image();
}

function change_image() {
    document.getElementById('Change_Image').src = 'http://placehold.it/100x100';
}

function change_back() {
    document.getElementById('Change_Image').src ='http://placehold.it/200x200';   
}

var initialTimout = 2000; //Time in milliseconds
var longInterval = 6000; //Time in milliseconds
var shortInterval = 300; //Time in milliseconds

setTimeout(start_animation, initialTimout);
setInterval(change_image, longInterval);
setInterval(change_back, shortInterval);

(Working demo at jsfiddle)

  1. 使用一个setInterval() 并在我们进行时更改间隔:
    • 这里的想法change_image()负责所有图像的变化,并根据显示的图像,改变setInterval的间隔。
    • 结果 - 此解决方案同时显示两个图像(初始超时时间),这不是目标。我研究了如何更改函数外部的变量,但肯定是弄错了,或者一旦调用了setInterval(),JS 就不允许更改间隔。

代码:

interval = 2000;

function change_image() {
    var url = document.getElementById('Change_Image').src;
    if (url == 'http://placehold.it/200x200') {
        document.getElementById('Change_Image').src = 'http://placehold.it/100x100';
        window.interval = 300;
    } else {
        document.getElementById('Change_Image').src = 'http://placehold.it/200x200';
        window.interval = 6000;
    }
}

setInterval(change_image, interval);

(Working demo at jsfiddle)

  1. 使用连续的setTimeout()
    • 这里的想法是让change_image()change_back() 在最初的2 秒超时后一遍又一遍地互相调用,并使用setTimeout() 来确保调用被延迟以及它们之间的时间是对的。
    • 结果 - 似乎根本不起作用:只显示图像 A。

代码:

function start_animation() {
    change_image();
}

function change_image() {
    document.getElementById('Change_Image').src = 'http://placehold.it/100x100';
    change_back();
}

function change_back() {
    document.getElementById('Change_Image').src ='http://placehold.it/200x200';   
}


setTimeout(start_animation, 2000);
setTimeout(change_back(), 300);
setTimeout(change_image(),6000);

(Working demo at jsfiddle)

有没有用 Javascript 解决这个问题的好方法?

怎么做?

【问题讨论】:

    标签: javascript image animation


    【解决方案1】:

    使用连续的setTimeouts 是要走的路(#3)。

    当您尝试在 300 毫秒到 6000 毫秒之间切换时,多个间隔(或根本没有间隔)会变得混乱。您正在考虑清除间隔或尝试以某种方式“同步”图像交换(但如果让它运行足够长的时间,您会看到图像 A 与图像交换太快B 等等)。

    这是一个演示连续超时的小提琴:

    http://jsfiddle.net/cCvtL/43/

    对于您的示例代码,您希望在计时器运行后连续设置它们,而不是一次设置所有计时器。对于2000 的初始超时值,我们检查undefined 值(来自初始循环调用)。之后,我们从setTimeouts 传递参数3006000

    function looper(url, interval){
        // If interval is undefined, we set the value to 2000 (initial)
        // Otherwise, we use the value passed in
        interval = interval === undefined ? 2000 : interval;
    
        // If url is present, we switch the image source
        if (url) {
            document.getElementById('Change_Image').src = url;
        } else {
            // Default, to keep things tidy.
            url = "http://placehold.it/200x200";
        }
    
        // Timer logic to handle the next iteration
        setTimeout(function() {
            if (url === "http://placehold.it/200x200") {
                looper("http://placehold.it/100x100", 300);
            } else {
                looper("http://placehold.it/200x200", 6000);
            }
        }, interval);
    }
    
    // Kick off the timer!
    looper();
    

    【讨论】:

      【解决方案2】:

      这是一个简单的技巧,你几乎明白了,你只需要设置超时

      function change_image() {
          var url = document.getElementById('Change_Image').src;
          console.log(url);
          if (url == 'wdw.tv.png') {
              setTimeout(function(){
                      document.getElementById('Change_Image').src = 'slmn.png';
                  }, 2000);
          } else {
              setTimeout(function(){
                      document.getElementById('Change_Image').src = 'wdw.tv.png';
                  }, 2000);
          }
      }
      
      setInterval(change_image, 4000);
      

      初始延迟为 4 秒,2 秒后将显示图像 A,然后每 2 秒在两者之间切换一次。

      只是玩弄间隔。虽然如果你有更多的图像,它会有所不同。 希望这可以帮助您继续前进。

      这里是 fiddle demo

      ****编辑****

      根据下面的评论,这可以消除不稳定的行为

      function change_image(url) {
          if(url){
              document.getElementById('Change_Image').src= url;
          }
          if (url == 'img1.png') {
              window.setTimeout(change_image, 300, 'img2.gif');
          } else {
              window.setTimeout(change_image, 6000, 'img1.png');
          }
      }
      
      setTimeout(change_image(), 2000);
      

      Demo Here

      【讨论】:

      • 我尝试了 jsfiddle 演示,它非常不稳定。我也认为这会遇到我在示例二中遇到的相同问题,整体 setInterval 与内部 setTimeouts 冲突。但感谢您试一试!我很感激。
      • 只是为了澄清:代码每 4 秒而不是每 2 秒在图像之间交替,而不是不稳定的。将 setInterval 设置为 2s 并将内部 setTimeouts 分别设置为 0,3 和 6,0 s 会产生我在上一条评论中提到的不稳定行为。
      【解决方案3】:

      在我的脑海中,Promise 可以在这里提供帮助;在您的情况下,这种一般(完全未经测试的伪代码)想法是否有意义? (这里,使用类似bluebird

      // Show an image, and returns a promise resolved after a number of ms 
      var showImage = function (src, howLong) {
      
         return new Promise(function (resolve, reject) {
      
           document.getElementById('Change_Image').src = src
           setTimeout(resolve, howLong)
      
         });
      
      }
      
      
      // The loop part
      var recur = function loop() {
        return showImage("url-of-imageB",300).then(function () {
             return showImage("url-of-imageA",6000)
        }).then(recur);
      }
      
      // Show A, then loop
      showImage("url-of-imageA",2000).then(recur);
      

      【讨论】:

      • 谢谢@phtrivier,在这种情况下,promise(我不知道它们,不得不阅读它们)会给最终用户或我带来任何特别的好处吗? (就像不阻塞用户端的执行一样/更快。)
      • 我认为他们会在代码的清晰度方面增加很多,这本身就是一件好事!此外,使用 promise 来表示异步行为增加了以有趣的方式组合异步函数的可能性(查看 Promise.all、Promise.catch 等...)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-24
      • 1970-01-01
      • 2023-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多