d3.js和document.onReady

时间:2011-08-24 01:08:49

标签: javascript d3.js

我刚刚开始使用d3.js并且有一个细节完全可以解除我的问题:如何在DOM准备好接收输入后才能执行代码?

当然,我可以使用像jQuery这样的东西,但这似乎过分了。

在我遇到的every d3.js example中似乎没有特殊的document.onReady()类型的例程,但所有示例都可以正常运行。但是,在我的测试代码中,如果在DOM准备好之前执行代码完全失败(将我的代码放入window.onload确认这一点)。

是什么给出了?

4 个答案:

答案 0 :(得分:46)

你会在他们的例子中注意到他们的javascript低于任何使用的html元素,以便在开始执行javascript之前加载部分dom。

简单地将你的javascript放在正文的底部通常就足够了。

答案 1 :(得分:5)

有时您不能依赖DIV / HTML元素放置,例如当您需要将用D3操纵的元素动态插入文档时。在这种情况下,一种解决方案是监视文档的DOMNodeInserted事件,并在回调中插入D3代码(我相信这排除了9之前的IE版本)。这是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");}
                 );
    }
});

答案 2 :(得分:3)

标记为正确的答案对我没有用,实际上是错误的。它是某种黑客攻击,不应被视为正确的答案。您可以在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 :(得分:2)

您可以在body上放置一个onload事件,并将所有d3js代码放在一个函数中。例如:

<body onload="yourFunctionName()">

在你的javascript中,插入:

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

只需将完整的d3示例代码粘贴到此函数中即可。在DOM准备就绪后,onload事件将发生。