2013-02-13 183 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

相關問題