gpt4 book ai didi

javascript - 如何使用 d3.js 创建

转载 作者:数据小太阳 更新时间:2023-10-29 05:17:24 26 4
gpt4 key购买 nike

我想使用 d3.js 从一些数据中创建一系列 dl 标签。

我想出的代码是这样的:

var x=d3.select("body")
.append('ol')
.selectAll('li')
.data(data)
.enter()
.append('li')
.append('dl')
.selectAll()
.data(d=>Object.entries(d.volumeInfo)).enter();

x.append('dt')
.text(d=>d[0]);

x.append('dd')
.text(d=>d[1]);

其中 data 是一个对象数组。一切正常,只是元素的顺序不正确。

这是我设法得到的订单:

<dl>
<dt>key1</dt>
<dt>key2</dt>
<dd>value1</dd>
<dd>value2</dd>
</dl>

但是应该是这样的:

<dl>
<dt>key1</dt>
<dd>value1</dd>
<dt>key2</dt>
<dd>value2</dd>
</dl>

我已经进行了大量的谷歌搜索,但没有任何答案可以回答这个问题,至少 not in a way that works in v5not with more than one dt/dd pair .

这似乎是 d3.js 应该能够做的基本事情。

最佳答案

在您的解决方案中:

x.append('dt')
.text(d=>d[0]);

x.append('dd')
.text(d=>d[1]);

所有附加有 enter().append() 循环的元素都附加到父级,按照它们附加的顺序,对于你来说这样运行:首先所有的 dt ,然后是所有 dd,如您所见。由 enter 语句创建的占位符节点(这些不是附加元素)不会以您可能期望的方式嵌套子节点。

尽管 d3 不包含使用像简单的 selection.append() 方法一样简单的方法来实现您正在寻找的方法,但可以相当容易地实现所需的行为标准的 d3 方法和额外的一两步。或者,我们可以自己将该功能构建到 d3.selection 中。

对于我的回答,我将以一个使用您的数据结构和输入模式的示例作为结束,但首先我将稍微简化这里的嵌套——而不是嵌套追加,我只是演示几种可能的追加方法有序的 sibling 。首先,我还简化了数据结构,但原理是一样的。


第一种方法可能是最直接的:使用 selection.each() 函数。通过输入选择(使用父级或输入的占位符),使用 each 方法附加两个单独的元素:

var data = [
{name:"a",description:"The first letter"},
{name:"b",description:"The second letter"}
];


d3.select("body")
.selectAll(null)
.data(data)
.enter()
.each(function(d) {
var selection = d3.select(this);

// append siblings:
selection.append("dt")
.html(function(d) { return d.name; });
selection.append("dd")
.html(function(d) { return d.description; })

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>


但是,也许更优雅的选择是深入研究 d3.selection() 并使用它来给我们一些新的行为。下面我添加了一个 selection.appendSibling() 方法,它允许您在选择的每个项目的正下方附加一个成对的兄弟元素:

d3.selection.prototype.appendSibling = function(type) {
var siblings = this.nodes().map(function(n) {
return n.parentNode.insertBefore(document.createElement(type), n.nextSibling);
})
return d3.selectAll(siblings).data(this.data());
}

它获取选择中的每个节点,创建指定类型的新配对兄弟节点(每个紧接在 DOM 中的原始节点之后),然后将新节点放入 d3 选择中并绑定(bind)数据。这允许您将方法链接到它上面以设置元素等的样式,并允许您访问绑定(bind)数据。请参阅下面的实际操作:

// modify d3.selection so that we can append a sibling
d3.selection.prototype.appendSibling = function(type) {
var siblings = this.nodes().map(function(n) {
return n.parentNode.insertBefore(document.createElement(type), n.nextSibling);
})
return d3.selectAll(siblings).data(this.data());
}

var data = [
{name:"a",description:"The first letter"},
{name:"b",description:"The second letter"}
];

d3.select("body")
.selectAll(null)
.data(data)
.enter()
.append("dt")
.html(function(d) { return d.name; })
.appendSibling("dd") // append siblings
.html(function(d) { return d.description; }) // modify the siblings
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

当然,将 sibling 放在单独的选择中可能是明智的,这样您就可以管理每个 sibling 的更新/进入/退出等。

此方法很容易应用于您的示例,这是一个嵌套解决方案,它使用的数据结构与您预期的一样,并且使用 appendSibling 方法:

// modify d3.selection so that we can append a sibling
d3.selection.prototype.appendSibling = function(type) {
var siblings = this.nodes().map(function(n) {
return n.parentNode.insertBefore(document.createElement(type), n.nextSibling);
})
return d3.selectAll(siblings).data(this.data());
}

var data = [
{volumeInfo: {"a":1,"b":2,"c":3}},
{volumeInfo: {"α":1,"β":2}}
]

var items = d3.select("body")
.append('ol')
.selectAll('li')
.data(data)
.enter()
.append('li')
.append('dl')
.selectAll()
.data(d=>Object.entries(d.volumeInfo)).enter();

var dt = items.append("dt")
.text(function(d) { return d[0]; })

var dd = dt.appendSibling("dd")
.text(function(d) { return d[1]; })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

关于javascript - 如何使用 d3.js 创建 <dl>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50122762/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com