mar*_*ton 2 javascript d3.js observablehq
我试图通过将新Date对象传递给data()函数,然后join()更新页面,使 D3 每秒更新一次 SVG 元素。我实际上是在一个Observable笔记本中使用的,Promises.tick()但我认为下面的代码(完整源代码)是相关位的粗略近似。我的最终目标是制作一个时钟,但这里的代码是我遇到的问题的最小演示。
这段代码的问题在于从未调用过updatein 函数join()——每次循环时enter都会调用该函数,这会导致text每次都追加一个新的函数。由于我有一个数据和一个元素,我希望join'supdate被调用,而不是enter. 我知道data()( example )上的 key 函数对于确定更改的内容很重要,但我的理解是默认键是数组索引,此处应始终为 0。无论如何,指定不同的键函数(从身份函数到返回常量)都没有帮助。
while (true) {
var data = [new Date()];
svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll("text")
.data(data)
.join(
enter => enter.append("text").text(d => "enter: " + d),
update => update.text(d => "update: " + d)
);
await new Promise(resolve => setTimeout(resolve, 1000));
}
Run Code Online (Sandbox Code Playgroud)
看这个:
svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
//etc...
Run Code Online (Sandbox Code Playgroud)
你是追加了新的<g>每次运行循环时间元素,毕竟所选元素(文本,或其他)将引用新追加的组,也就是selectAll选择所有文本里面是新追加的组。显然,没有。这就是为什么您总是只有输入选择,而没有更新选择的原因。
看看这个演示,重现你的问题:
svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
//etc...
Run Code Online (Sandbox Code Playgroud)
var body = d3.select("body");
function foo(data) {
var div = body.append("div")
.selectAll("p")
.data(data)
.join(
enter => enter.append("p").html(d => "enter: " + d),
update => update.html(d => "update: " + d)
);
};
foo([Math.random()]);
d3.interval(function() {
foo([Math.random()])
}, 1000)Run Code Online (Sandbox Code Playgroud)
假设您只想将组附加一次,您可以执行以下操作:
var g = svg.selectAll(".myGroup")
.data([true]);
g = g.enter()
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.merge(g);
g.selectAll("text")
.data(data)
.join(
enter => enter.append("text").text(d => "enter: " + d),
update => update.text(d => "update: " + d)
);
Run Code Online (Sandbox Code Playgroud)
这里,data([true])表示数据本身无关紧要,它只是一个单独的真值,用于附加单个组元素。
这是一个演示,展示了它是如何工作的:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>Run Code Online (Sandbox Code Playgroud)
var g = svg.selectAll(".myGroup")
.data([true]);
g = g.enter()
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.merge(g);
g.selectAll("text")
.data(data)
.join(
enter => enter.append("text").text(d => "enter: " + d),
update => update.text(d => "update: " + d)
);
Run Code Online (Sandbox Code Playgroud)