web-dev-qa-db-ja.com

d3.jsおよびdocument.onReady

私は d3.js を使い始めたばかりで、完全にわかりにくい1つの詳細があります。DOMが入力を受け取る準備ができた後でのみ、コードを実行するにはどうすればよいですか?

もちろん、jQueryのようなものを使用することもできますが、それは過度に思えます。

すべてのd3.jsの例 で特別なdocument.onReady()タイプのルーチンはないようですが、すべての例は問題なく動作します。ただし、私の側でコードをテストするとき、DOMの準備ができる前にコードを実行すると、コードは完全に失敗します(コードをwindow.onloadはこれを確認します)。

何ができますか?

30
Roshambo

それらの例では、JavaScriptが、JavaScriptの実行を開始する前にDOMの一部が読み込まれるように、使用されているHTML要素の下にあることがわかります。

通常、JavaScriptを本体の下部に配置するだけで十分です。

46
Jon D. Koon

たとえば、D3で操作された要素をドキュメントに動的に挿入する必要がある場合など、DIV/HTML要素の配置に依存できないことがあります。そのような状況での1つの解決策は、DOMNodeInsertedイベントのドキュメントを監視し、D3コードをコールバックに挿入することです(ただし、これはIE 9より前のバージョンは除外されます)。jQueryの例を次に示します。

$(document).bind('DOMNodeInserted', function(event)
{
    if (event.target.id == "viz")
    {
        var sampleSVG = d3.select("#viz")
                 .append("svg:svg")
                 .attr("width", 100)
                 .attr("height", 100);    

        sampleSVG.append("svg:circle")
                 .style("stroke", "gray")
                 .style("fill", "white")
                 .attr("r", 40)
                 .attr("cx", 50)
                 .attr("cy", 50)
                 .on("mouseover", function() {
                      d3.select(this).style("fill", "aliceblue");
                 })
                 .on("mouseout", function() {
                      d3.select(this).style("fill", "white");}
                 );
    }
});
5
mz2

正しいとマークされた答えは私にはうまくいきませんでした、そして実際には間違っています。これは一種のハックであり、正解とは見なされません。同じように、setTimeout(function(){..}、1000)内でコードを実行することもできます。遅延を設定できるので、さらに信頼性が高くなります:-/

私の場合、実際の寸法を知るために、すべての要素が処理されるのを待つ必要がありました。それらが構築、処理、完了されていない場合、数値は正しくありませんでした。

更新されました。これが正解です。

ほとんどの場合、d3.json()のような非同期呼び出しを使用してDOMを構築するためのデータを取得します。そのため、時間がかかります。非同期呼び出しは非ブロッキングであるため、非同期呼び出しが終了する前でも後続のコードが呼び出され、問題が発生します。これが、この質問を投稿した理由です。

したがって、D3または他のどこかで何かを探すことによってこれを解決しようとしています。これは、D3非同期呼び出しが終了し、次のことができるようになったことを示します。同期ajax呼び出しを行うことを提案する人もいます。これはひどく間違っています。非同期呼び出しは非同期になるように作成されます。

実際に必要なことは、パラダイムを変えることです。その非同期呼び出しにコールバックを渡すだけで、それだけです!そんな感じ:

function thingsToDoWhenDOMisBuilt() {
    ...
}

function buildDOM(rootNode, error, thingsToDoWhenDOMisBuilt) {
    ...
    // everything is built, so we can do our post-build thing against DOM
    if (thingsToDoWhenDOMisBuilt)
        thingsToDoWhenDOMisBuilt()
}

d3.json(urlToData, buildDOM) {
    if (error)
        console.log("oops")
    buildDOM(rootNode, thingsToDoWhenDOMisBuilt)
}

また、 async.js も見てください

上で提案されたイベントのバインドも恐ろしい考えです。代わりに.enter().exit()を使用してください。 D3はデータ駆動型であり、イベント駆動型のフローが必要な場合は、jQueryまたはVanilla JSを使用してください。

3
dehumanizer

本体にonloadイベントを配置し、すべてのd3jsコードを関数に配置できます。例えば:

<body onload="yourFunctionName()">

そしてあなたのjavascriptにこれを挿入してください:

function yourFunctionName() {
    //Your d3js code goes here
}

この関数内に完全なd3サンプルコードを貼り付けるだけです。 onloadイベントは、DOMの準備ができた後に発生します。

2
Anonymous