2013-02-13 237 views
7

我基本上试图通过LI标记的集合进行循环,并插入一些文本来模拟某人编写要做的事情列表的外观。它可以工作,但它会同时写入每个列表项,而不是等待。有没有简单的方法来实现这一目标?我有一个JS小提琴安装在这里:http://jsfiddle.net/fZpzT/但代码看起来像这样。谢谢。jquery .each等待函数在继续循环之前完成

function addListItems() { 
var str = { 
    listitem1:'personal background check', 
    listitem2:'look into my sketchy neighbor', 
    listitem3:'look up my driving record', 
    listitem4:'pick up milk', 
    listitem5:'wash the car' 
} 

$('.list-container li').each(function(){ 
    var z = $(this).attr('id'); 
    var str2 = str[z]; 
    var delay = 0; 
    for (var i = 0; i <= str2.length; i++) { 
     (function(str2){ 
      delay += 100 + Math.floor(Math.random()*11)*6; 
      setTimeout(function(){ 
       appendStr(str2);  
      },delay); 
     })(str2[i]) 
    } 
    function appendStr(str2) { 
     $('#'+ z).append(str2); 
    } 
}); 
} 
+0

1用于阱书面问题和的jsfiddle例子。我不能立即确定*解决方案*是什么,但我很确定问题是**不是**'.each()',而是使用'setTimeout()'。 'setTimeout()'是异步执行的,这意味着整个循环迭代完成(不是同时),但完成*非常快*,然后'setTimeout'函数处理程序在循环结束后开始工作。 – Snixtor 2013-02-13 01:57:54

+2

我会在[这里](http://api.jquery.com/category/deferred-object/)寻找关于如何使用'deferred'链接这些函数的一些想法。 – Aesthete 2013-02-13 02:03:18

+0

我同意Snixtor的解释,并补充说,你应该根据你正在使用的列表项来增加延迟值(你可以使用'each(function(index){...'来获得索引)。第一个项目需要延迟,但是你可以延迟第二个项目1秒,第三个和第二个等等,这会增加每秒添加一个列表项的效果。 – 2013-02-13 02:03:24

回答

1

如何简化?使用两个变量在单个循环中迭代略有修改的数据结构的全部内容。喜欢这个。 http://jsfiddle.net/cXykd/

var strings = 
[ 
    { "id":"listitem1", "text": "write the first item" }, 
    { "id":"listitem2", "text": "write the second item" }, 
    { "id":"listitem3", "text": "write the third item" }, 
    { "id":"listitem4", "text": "write the fourth item" }, 
    { "id":"listitem5", "text": "write the fifth item" }, 
] 

var stringsIndex = 0; 
var textIndex = 0; 

AddString(); 

function AddString(){ 
    if (stringsIndex < strings.length){ 
     if (textIndex >= strings[stringsIndex].text.length) 
     { 
      stringsIndex++; 
      if (stringsIndex == strings.length) 
      { 
       return; 
      } 
      textIndex = 0; 
     } 

     $("#" + strings[stringsIndex].id).append(strings[stringsIndex].text[textIndex]); 
     textIndex++; 

     var delay = 10 + Math.floor(Math.random()*11)*6; 
     setTimeout(AddString, delay); 
    } 
} 
+0

感谢Snixtor。我最终选择了这个解决方案,因为这对我来说是最容易理解的,因为我必须在整个事情完成后添加一个回调函数,并且在每次遍历字符串之后添加一些附加功能。 – Brian 2013-02-13 18:36:03

4

使延迟累计:Demo on jsFiddle

var str = { 
    listitem1: 'write the first item', 
    listitem2: 'write the second item', 
    listitem3: 'write the third item', 
    listitem4: 'write the fourth item', 
    listitem5: 'write the fifth item' 
}, cumulativeDelay = 0; 

$('.list-container li').each(function() { 
    var z = $(this).attr('id'); 
    var str2 = str[z]; 
    var delay = cumulativeDelay; 
    for (var i = 0; i <= str2.length; i++) { 
     (function (str2) { 
      delay += 100 + Math.floor(Math.random() * 11) * 6; 
      setTimeout(function() { 
       appendStr(str2); 
      }, delay); 
     })(str2[i]) 
    } 
    cumulativeDelay = delay; 
    function appendStr(str2) { 
     $('#' + z).append(str2); 
    } 
    $(this).css('color', 'red'); 
}); 
+1

不需要额外的变量。可以简单地将'var delay = 0;'移到'each'之外来实现相同的结果。 – Jrod 2013-02-13 03:17:35

+1

感谢弗洛伊德。我使用Snixtor的解决方案,因为我更喜欢它,然后是我最初的那个,但是使用我现有的代码来寻找解决方案。 – Brian 2013-02-13 18:38:52

2

我会反向运作:

  1. 你开始要写入字符串,
  2. 对于每个字符串:

    1. 找到相应的列表项(通过编号)
    2. 用打字机风格编写整个字符串
    3. 完成后调用下一次迭代。

      var strings = [ 
          'personal background check', 
          'look into my sketchy neighbor', 
          'look up my driving record', 
          'pick up milk', 
          'wash the car' 
      ]; 
      
      function iterate(strings, idx) 
      { 
          if (idx >= strings.length) { return; } 
      
          var id = 'listitem' + (idx + 1), 
          el = document.getElementById(id); 
      
          typewriter(el, strings[idx], 0, function() { 
          iterate(strings, idx + 1); 
          }); 
      } 
      
      function typewriter(el, str, idx, cb) 
      { 
          if (idx >= str.length) { 
          return cb(); 
          } 
      
          setTimeout(function() { 
          el.innerText = str.substr(0, idx + 1); 
          typewriter(el, str, idx + 1, cb); 
          }, 100 + Math.floor(Math.random() * 11) * 6); 
      } 
      

Demo

+0

谢谢杰克。我最终选择了Snixtor的解决方案,但您的解决方案也非常出色。 – Brian 2013-02-13 18:37:43

相关问题