javascript - d3.join() 输入调用而不是更新?
问题描述
Date
我试图通过将一个新对象传递给函数来使 D3 每秒更新一次 SVG 元素data()
,然后join()
更新页面。我实际上是在Observable笔记本中使用Promises.tick()
的,但我认为下面的代码(完整源代码)是相关位的粗略近似。我的最终目标是制作一个时钟,但这里的代码是我遇到的问题的最小演示。
这段代码的问题是update
函数 injoin()
永远不会被调用——每次循环时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));
}
解决方案
看这个:
svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
//etc...
每次运行循环时都会附加一个新<g>
元素,之后所有选定的元素(文本或其他)都将引用该新附加的组,即选择该新附加组内selectAll
的所有文本。显然,没有。这就是为什么您总是只有一个输入选择,而没有更新选择。
看看这个演示,重现你的问题:
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)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>
假设您只想将组附加一次,您可以执行以下操作:
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)
);
这里,data([true])
表示数据本身无关紧要,它只是一个真实值,用于附加单个组元素。
这是一个演示它是如何工作的演示:
var body = d3.select("body");
function foo(data) {
var div = body.selectAll(".myDiv")
.data([true]);
div = div.enter()
.append("div")
.attr("class", "myDiv")
.merge(div);
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)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>
推荐阅读
- python - Flask restful/sqlalchemy update/setattr 多个dict同时
- python - Jupyter 无法识别刚刚安装的模块 pip
- c# - APReleaseProcess_Extension 自定义代码在 Acumatica ERP 版本 2017 R2 中不起作用
- reactjs - 材质 UI 网格间距属性不起作用
- xampp - 如何通过 xampp 运行联系表单
- html - 如何在 Wordpress HTML5 视频中禁用画中画模式
- python - Python - 如何使用 .click/selenium 打印 URL
- databricks - Databricks - 将 dbfs:/FileStore 文件下载到我的本地计算机
- regex - 有没有办法在括号中转义连字符?
- apache-kafka - Producer 正在发布到 Kafka,但无法从 Spark 结构化流中读取