【问题标题】:Changing images using delays使用延迟更改图像
【发布时间】:2016-06-22 22:24:11
【问题描述】:

我正在尝试弄清楚如何使用三张图像的顺序制作动画。

默认图像是“image1.png”,在页面加载时始终显示。

  1. 每 5 秒后,变量“back.src”必须突然改变 到 image2.png,所以不会褪色。默认为 image1.png

  2. 然后在 0.5 秒后,变量再次更改,但随后变为 image3.png.

  3. 0.5 秒后变回 image2.png

  4. 0.5 之后又回到 image1.png。

这是循环重复的,因为我想在 5 秒后再次重复该过程。

我的问题是,我不知道构建这段代码是否是最好的方法。根据上述要求,我的代码应该是什么样子?

这是我到目前为止的代码:

var back = new Image();
back.src = "image1.png";
        function wait(miliseconds) {
            var currentTime = new Date().getTime();
            while (currentTime + miliseconds >= new Date().getTime()) {
            }
        }

        function image1() {
            wait(5000);
            back.src = "image2.png";
        }

        function image2() {
            wait(500);
            back.src = "image3.png";
        }

        function image3() {
            wait(500);
            back.src = "image2.png";
        }


function animate(){
    ctx.save();
    ctx.clearRect(0, 0, cW, cH);
    ctx.drawImage(back,0,0);        
    ctx.restore();
}
var animateInterval = setInterval(animate, 30);

【问题讨论】:

  • setInterval代替while怎么样?
  • 这看起来像一个非常阻塞的代码。

标签: javascript jquery


【解决方案1】:

在 Javascript 中没有wait() 操作,并且通常试图让一个像你正在做的事情会导致坏事发生(事件循环被饿死,用户界面被锁定等等......)。相反,您可以使用setTimeout() 安排未来运行。这允许 JS 引擎在您等待下一次循环迭代时执行其他操作(例如为系统中发生的其他事件提供服务),这在 Javascript 中通常非常重要。

我建议你把你想要的序列放入一个数据结构中,然后使用一个遍历数据结构的计时器,当它到达结束时包装:

var data = [
  ["image1.png", 5000],
  ["image2.png", 500],
  ["image3.png", 500],
  ["image4.png", 500]
];

function runAnimation() {
    var index = 0;

    function animate(image){
        ctx.save();
        ctx.clearRect(0, 0, cW, cH);
        ctx.drawImage(image,0,0);        
        ctx.restore();
    }

    function next() {
       var img = new Image();
       img.src = data[index][0];
       animate(img);

       // schedule next iteration 
       var t = data[index][1];

       // increment and wrap index if past end
       index = (index + 1) % data.length;

       setTimeout(next, t);
    }

    next();

}

为了使这项工作正常进行,您需要预先缓存您的图像,以便它们立即加载。如果您不打算预缓存图像,则需要添加 onload 处理程序,以便知道图像何时完成加载并准备好绘制。

这里有关于预缓存图像的信息:How do you cache an image in Javascript

或者,为了确保您的图像在绘制之前已加载,您可以使用onload 处理程序,如下所示:

var data = [
  ["image1.png", 5000],
  ["image2.png", 500],
  ["image3.png", 500],
  ["image4.png", 500]
];

function runAnimation() {
    var index = 0;

    function animate(image){
        ctx.save();
        ctx.clearRect(0, 0, cW, cH);
        ctx.drawImage(image,0,0);        
        ctx.restore();
    }

    function next() {
       var img = new Image();
       var nextSrc = data[index][0];
       img.onload = function() {
           animate(img);

           // schedule next iteration 
           var t = data[index][1];

           // increment and wrap index if past end
           index = (index + 1) % data.length;

           setTimeout(next, t);
       };
       img.src = nextSrc;
    }

    next();

}

【讨论】:

  • 我会使用t = data[index = index++%data.length][1] 而不是if (index >= data.length) { index = 0; }
  • @Redu - 我修改为使用该建议。
【解决方案2】:

你可以使用setIterval()实现它

了解 JS 计时器 Here

这是您需要的:https://jsfiddle.net/nfe81zou/3/

var image1 = "https://pixabay.com/static/uploads/photo/2016/06/17/13/02/duck-1463317_960_720.jpg";
var image2 = "https://pixabay.com/static/uploads/photo/2013/09/22/16/56/duck-185014_960_720.jpg";
var image3 = "https://pixabay.com/static/uploads/photo/2013/11/02/03/23/ducks-204332_960_720.jpg";

$(function() {
  $("#image").prop("src", image1);
  setInterval(function() {
$("#image").prop("src", image2);
setTimeout(function() {
  $("#image").prop("src", image1);
  setTimeout(function() {
    $("#image").prop("src", image3);
  }, 500);
  setTimeout(function() {
    $("#image").prop("src", image2);
  }, 1000);
}, 1500);
  }, 5000);
});
#image {
  border: 2px solid red;
  width: 400px;
  height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img src="" id="image"/>

【讨论】:

  • 这个时机不能正常工作。每 500 毫秒,您将绘制图像 3。但是在 1000 的倍数的间隔上,您还将绘制 image2,而在 1500 的倍数的间隔上,您还将绘制 image1。这不是你想要的。没有可靠的保证在您的所有间隔之间进行排序,并且您正在对您甚至不想绘制的值进行各种额外的设置或.src。我不推荐这种方法。
  • @jfriend00 现在怎么样?注意超时和间隔
  • 应该在它们之间保持完美协调的多个间隔计时器在 Javascript 中并不是一个好的设计实践。不能保证间隔计时器完全准确。
  • 你几乎明白了!第一张图片在页面加载后仅持续 5 秒,然后像其他图片一样在 0.5 之后才开始变化。你会如何调整它?
  • 查看更新,根据需要订购图片。
【解决方案3】:

这将是我解决这个问题的方法。图片按顺序显示

0 (5000ms) -> 1 (500ms) -> 2 (500ms) -> 1 (500ms) -> 0 (5000ms) ...

这里没有setInterval()。此代码使用伪递归setTimeout() 实现。

var images = ["http://1.bp.blogspot.com/_ZRj5nlc3sp8/S-T7vOsypQI/AAAAAAAADBo/0kYfB8BM6zE/s320/beautiful+girl+pics+1.jpg",
              "http://1.bp.blogspot.com/-w4UtHwbrqBE/ViNbJWhnmvI/AAAAAAAADtY/hGbRtz993Tg/s1600/face%2Bwallpapers%2B%25282%2529.jpg",
              "http://2.bp.blogspot.com/-4kZ9Iu8QTws/ViNbL3S29fI/AAAAAAAADtw/QakqQE72N1w/s1600/face%2Bwallpapers%2B%25286%2529.jpg"],
      imel = document.getElementById("photo");
function displayImages(idx,fwd){
  var ms = 0;
  idx = idx || 0;    // we could also use the ES6 default value method.
  if (idx === 0) {
    fwd = !fwd;      // when index becomes 0 switch the direction of the loop
    ms = fwd ? 5000  // if backwards rearrange index and duration to 0.5 sec
             : (idx = images.length - 2, 500);
  } else ms = 500;   // when index is not 0 set the duration to 0.5 sec
  imel.src = images[idx];
  fwd ? setTimeout(function(){displayImages(++idx % images.length,fwd)},ms)
      : setTimeout(function(){displayImages(--idx,fwd)},ms);
}

displayImages();
&lt;image id ="photo"&gt;&lt;/image&gt;

【讨论】:

  • 我特别喜欢我在这里看到的。此外,代码还不错:P 谢谢!
猜你喜欢
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多