我刚刚开始使用d3.js并且有一个细节完全可以解除我的问题:如何在DOM准备好接收输入后才能执行代码?
当然,我可以使用像jQuery这样的东西,但这似乎过分了。
在我遇到的every d3.js example中似乎没有特殊的document.onReady()
类型的例程,但所有示例都可以正常运行。但是,在我的测试代码中,如果在DOM准备好之前执行代码完全失败(将我的代码放入window.onload
确认这一点)。
是什么给出了?
答案 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事件将发生。