簡體   English   中英

來自元素childNodes的Javascript打字機效果

[英]Javascript Typewriter Effect from element childNodes

我正在嘗試創建一個類型編寫器效果,它將獲取元素的節點,然后以給定的速度順序顯示這些節點的值。 如果節點是文本節點,我希望它進入並順序顯示該文本中的每個字符。

HTML:

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<!-- item will be appened to this layout -->
<div id="log" class="sl__chat__layout">
</div>


<!-- chat item -->
<script type="text/template" id="chatlist_item">

  <div data-from="{from}" data-id="{messageId}" id="messageID">
    <div id="messageBox">

    <span id="message">
      {message}
    </span>

    </div>
  </div>
</script>

使用Javascript:

// Please use event listeners to run functions.
document.addEventListener('onLoad', function(obj) {
    // obj will be empty for chat widget
    // this will fire only once when the widget loads
});

document.addEventListener('onEventReceived', function(obj) {
    // obj will contain information about the event
e++  
typeEffect(e);  
});

var speed = 50;
var e = 1;

function typeEffect(inp) {
    var o = inp;
    document.getElementById("messageID").id= "messageID"+o;
    document.getElementById("message").id= "message"+o;
    var text = $("#message"+o).text();
    $("#message"+o).text('');

    var i = 0;
    var timer = setInterval(function() {
        if(i < text.length) {
            $("#message"+o).append(text.charAt(i));
            i++;
        }

        else{
            clearInterval(timer);
        };   
  }, speed);

    }                    

以下是id為“message2”的元素示例。 如您所見,它包含一些文本,然后是包含圖像的跨度,然后是一些文本。

   <span id="message2">
      Hello 
      <span class="emote">
         <img src="https://static-cdn.jtvnw.net/emoticons/v1/1251411/1.0"> 
      </span> 
      There
    </span>

在我上面發布的代碼中,我能夠創建文本的打字機效果。 但是,使用上面的例子,我無法找到一種方法來鍵入“Hello”然后鍵入帶有圖像的跨度然后“There”。

我試圖得到這樣的節點:

   var contents = document.getElementById("message"+o).childNodes;

當我將其記錄到控制台時,我得到:NodeList(3)[text,span.emote,text]

但是從那里我無法訪問nodeValues。 我一直在犯錯誤。 我不確定我做錯了什么。 從那里我也不確定正確的方法來清空“消息”+ o元素,然后用信息重新填充它。

希望這能解釋一切!

通過使用$.text() ,您將獲得Element的textContent ,並且其所有標記內容都已消失(實際上是其所有子項)。

為了保留此內容,您需要存儲DOM節點而不僅僅是textContent
從那里開始,你將不得不分離DOM樹並在附加每個Element時移動它,在每個TextNode的textContent緩慢迭代。

但是,這樣做並不容易。 實際上,我們將在文檔中重新附加DOM節點的事實意味着我們正在行走的分離的DOM樹將被破壞。

為了避免這種情況,我們因此需要創建一個分離的DOM樹的副本,我們將保持完整,所以我們可以繼續走它,就像它是原始的一樣。
並且為了知道在哪里放置元素,我們需要將每個原始節點存儲為克隆的屬性。

為此,我們將創建兩個TreeWalkers ,一個用於原始節點,另一個用於克隆版本。 通過同時行走,我們可以輕松地設置克隆的.original屬性。
然后,我們必須回到我們的克隆TreeWalker的根,然后再次開始它,這次能夠將正確的節點附加到其原始的parentNode。

 async function typeWrite(root, freq) { // grab our element's content const content = [...root.childNodes]; // move it to a documentFragment const originals = document.createDocumentFragment(); originals.append.apply(originals, content); // clone this documentFragment so can keep a clean version of the DOM tree const clones = originals.cloneNode(true); // every clone will have an `original` node // clones documentFragment's one is the root Element, still in doc clones.original = root; // make two TreeWalkers const originals_walker = document.createTreeWalker(originals, NodeFilter.SHOW_ALL, null); const clones_walker = document.createTreeWalker(clones, NodeFilter.SHOW_ALL, null); while(originals_walker.nextNode() && clones_walker.nextNode()) { // link each original node to its clone clones_walker.currentNode.original = originals_walker.currentNode } while(clones_walker.parentNode()) { // go back to root } // walk down only our clones (will stay untouched now) while(clones_walker.nextNode()) { const clone = clones_walker.currentNode; const original = clone.original; // retrieve the original parentNode (which is already in doc) clone.parentNode.original .append(original); // and append the original version of our currentNode if(clone.nodeType === 3) { // TextNode const originalText = original.textContent; // we use a trimmed version to avoid all non visible characters const txt = originalText.trim().replace(/\\n/g, ''); original.textContent = ''; // in doc => empty for now let i = 0; while(i < txt.length) { await wait(freq); // TypeWriting effect... original.textContent += txt[i++]; } // restore original textContent (invisible to user) original.textContent = originalText; } } } typeWrite(message2, 200) .catch(console.error); function wait(time) { return new Promise(res => setTimeout(res, time)); } 
 <span id="message2"> Hello <span class="emote"> <img src="https://static-cdn.jtvnw.net/emoticons/v1/1251411/1.0"> </span> There </span> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM