2

これが私の関数です。

    function duplicate_step_through_highlighted (element_jq, target_jq, char_cb) {
        console.log( element_jq);
        var contents = element_jq.contents();
        for (var i = 0 ; i < contents.length; ++i) {
            // if text node, step
            if (contents[i].nodeType === 3) {
                // insert empty text node
                var new_tn = document.createTextNode('');
                target_jq.append(new_tn);

                // iterate it 
                var text = contents[i].nodeValue;
                for (var j = 0; j < text.length; j++) {
                    char_cb(text[j],new_tn);
                    new_tn.nodeValue += text[j];
                    // *** I want an async delay here *** 
                }
            } else { // type should be 1: element
                // target_jq gets a duplicate element inserted, copying attrs
                var new_elem = $(contents[i].cloneNode(false)).appendTo(target_jq);
                duplicate_step_through_highlighted($(contents[i]),$(new_elem),char_cb);

                // then a recursive call is performed on the newly created element as target_jq
                // and the existing one as element_jq. char_cb is passed in
            }
        }
    }

私がやっていることは、一度に1文字ずつ再構築することによってHTML要素を再構築することです。これを行うのには十分な理由があります。「入力」される視覚効果が必要です。

だから今は遅れがないので私の要素は即座に複製されます。結果に一貫性があることを確認しましたが、各文字が挿入された後に非同期遅延を設定できるようにするには、機能を完全に書き直す必要があることが明らかになりつつあります。

それを書き直して、要素内の自分の位置を追跡するためのスタックを用意する必要がありますか?

4

3 に答える 3

4

このような効果を実装する方法については、私の最近の回答またはこの古い回答( Demo ) を参照してください。


ヒント: 要素を新しい要素に複製しないでください。要素を非表示にして、パーツごとに表示するだけです。

また、ネイティブ DOM 要素以外は jQuery インスタンスをまったく処理しない方が簡単な場合があります。そうです、書き直せばいいかもしれません:-)そして、スタックも必要だと思います。

function animate(elements, callback) {
/* get: array with hidden elements to be displayes, callback function */
    var i = 0;
    (function iterate() {
        if (i < elements.length) {
            elements[i].style.display = "block"; // show
            animateNode(elements[i], iterate); 
            i++;
        } else if (callback)
            callback();
    })();
    function animateNode(element, callback) {
        var pieces = [];
        if (element.nodeType==1) {
            while (element.hasChildNodes())
                pieces.push(element.removeChild(element.firstChild));
            setTimeout(function childStep() {
                if (pieces.length) {
                    animateNode(pieces[0], childStep); 
                    element.appendChild(pieces.shift());
                } else
                    callback();
            }, 1000/60);
        } else if (element.nodeType==3) {
            pieces = element.data.match(/.{0,2}/g); // 2: Number of chars per frame
            element.data = "";
            (function addText(){
                element.data += pieces.shift();
                setTimeout(pieces.length
                    ? addText
                    : callback,
                  1000/60);
            })();
        }
    }
}

animate($("#foo").children());

jsfiddle.net のデモ

使い方:

  • このaddText関数は、現在のテキスト ノードに文字を追加し、それ自体のタイムアウトを設定します - アニメーション! すべてが完了すると、関数が呼び出されcallbackます。
  • childStep子ノードでアニメーションを実行し、子ノードがなくなるまで自分自身をコールバックとして渡し、その後callback関数を呼び出します。
  • 両方ともanimateNode、ノード ツリーを再帰的に実行し、テキストノードをその順序でアニメーション化します。
  • iterate関数は、animateNodeコールバックとして自身を渡すことにより、すべての入力要素に対して (それらをアンハイドした後に) 呼び出します。すべての入力要素が終了するとcallback、 の 2 番目の引数として指定されたアウターを呼び出しますanimate
于 2012-07-26T08:58:30.783 に答える