【问题标题】:my code doesn't work with two setintervals我的代码不适用于两个 setintervals
【发布时间】:2013-12-09 15:34:34
【问题描述】:

我希望我的代码使用 moment.js 获取特定时间,将其与“帧”编号相关联,然后使用该编号填充 url 以获取序列中的指定图像。然后,该 url 将以 500 毫秒的速率遍历一系列图像 url(它们是小图像,例如 20k)。我使用名为 getframe 的 setInterval 函数来做到这一点。

但为了确保我的帧迭代器不会因为滞后太远,我还想运行另一个名为 gettime 的 setinterval,它会根据新的 moment.js 时间戳更新帧变量。我每 10000 毫秒运行一次。问题是我的代码不适用于这两个同时运行的 setInterval。如果我从 setinterval 中取出函数 gettime 它工作正常但是当我把它放回去时它会停止并且我不知道为什么?

欢迎有关如何更有效地进行此 gettime 更新的建议,但我的 jquery 技能非常有限(抱歉),因此您必须非常详细地解释为什么/如何工作..

<!DOCTYPE html>
<html>
  <head>
    <script src="three/js/moment.js"> </script>
    <script src="three/js/jquery-2.0.3.js"></script>
  <style>
  .frames { position:relative; width:500px; height:332px; }
  .frames img { position:absolute; left:0; top:0; }
  </style>
  <head>

  <body>

<img id ="frame_placeholder">

<script>





  window.onload = $(function (){

    setInterval(gettime,10000);

    setInterval(getframe,500); 

    function gettime(){
      now = moment().zone('-0500')

      if (now.hour() >= 18) {
      now = now.subtract('hour', 18).subtract('minute', 30)
      } else {
      now = now.add('hour', 6).add('minute', 30)
        };

    var frame = ((now.hour() * 3600) + (now.minute() * 60) + now.second()) * 2;


    };


    function getframe(){
      var framestr=frame.toString();
                            function pad (str, max) 
                            {
                              return str.length < max ? pad("0" + str, max) : str;
                            }; 

      framerun = pad (framestr,5);

      var src = "https://s3.amazonaws.com/image"+ framerun +".jpg"

      framerun1=parseInt(framerun)
      $("#frame_placeholder").attr("src", src);
      frame=framerun1+=1;

    }

  });






</script>

  </body>
  </html>

【问题讨论】:

  • 你的控制台说什么?抛出任何错误? gettime 是否自行运行(没有 getframe)?
  • 框架未在 getframe() 中定义

标签: jquery setinterval


【解决方案1】:

jsFiddle Demo

你的变量的范围是这里的罪魁祸首。 frame 在本地范围内限定为 gettime ,因此当它在 getframe 中使用时,框架未定义并且出现错误。这可以通过将 frame 变量放置在 onload 函数内部但在 gettime 之外、从框架的 gettime 中删除 var 以及在 getframe 中放置未定义的检查来解决。

setInterval(gettime,10000);
setInterval(getframe,500); 

var frame;

function gettime(){
 now = moment().zone('-0500');

 if (now.hour() >= 18) {
  now = now.subtract('hour', 18).subtract('minute', 30);
 } else {
  now = now.add('hour', 6).add('minute', 30);
 }
 frame = ((now.hour() * 3600) + (now.minute() * 60) + now.second()) * 2;
}
function getframe(){
 var framestr = frame? frame.toString() : "";
 function pad (str, max){
  return str.length < max ? pad("0" + str, max) : str;
 }
 framerun = pad (framestr,5);
 var src = "https://s3.amazonaws.com/image"+ framerun +".jpg";
 framerun1=parseInt(framerun);
 $("#frame_placeholder").attr("src", src);
 frame=framerun1+=1;
}

【讨论】:

  • 太棒了!这似乎是正确的轨道 - 现在的问题似乎是 gettime 在加载时等待运行约 10 秒(不知道这是因为它等待一个间隔运行还是什么?)等等框架没有由 gettime 的时间戳正确定义
  • 也许我可以把gettime放在'onload'之前,有没有一些jscript命令可以让gettime优先于getframe?
  • @user3079080 - 要立即运行它,只需在 onload 函数结束时调用它。 gettime();
【解决方案2】:

这并不能真正回答您的直接问题,但如果您尝试设置动画以每半秒更改一次,您可能需要使用 Javascript Image 对象预加载图像:

var frames = [];
var loadCount = 0;
function preloadImages() {
  for (var i = 0; i < TOTAL_FRAMES; i++) {
    loadFrame("myurl" + i + ".jpg", i);
  }
}

function loadFrame(url, frameNumber) {
  var img = new Image();
  img.src = url;
  img.onload(function() {
    frames[frameNumber] = img;
    loadCount++;
    if (loadCount == TOTAL_FRAMES) {
      startAnimation();
    }
  });
}

基本上,这会遍历您的所有图片 URL,下载它们并将它们存储在一个数组中,然后在每个 URL 之后运行一个回调。如果所有图像都已下载,您的动画就会开始,您不必担心从服务器加载图像。此外,您的帧被组织在一个数组中,您可以在运行动画时简单地循环它们。

【讨论】:

  • 感谢这个想法——你说得对,最好的方法是某种预加载数组。问题是图像的数量很大——100,000(基本上我是在模拟一种定格电影)所以我不能把它们都放在那个数组中。我可能会尝试制作某种动态循环,在调用每个图像后,它会被目录中的新图像替换,因此当它返回循环中的那个位置时,它实际上会在序列中进一步显示图像,但不确定我有编码才能让它工作......
猜你喜欢
  • 1970-01-01
  • 2015-12-10
  • 2016-01-01
  • 2014-05-25
  • 2020-11-27
  • 1970-01-01
  • 2017-10-29
  • 1970-01-01
  • 2013-03-01
相关资源
最近更新 更多