我想dl使用d3.js从一些数据列表中创建一系列标签.
我想出的代码是这样的:
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]);
Run Code Online (Sandbox Code Playgroud)
其中data是一个对象数组.除了元素的顺序不正确外,一切正常.
这是我设法得到的订单:
<dl>
<dt>key1</dt>
<dt>key2</dt>
<dd>value1</dd>
<dd>value2</dd>
</dl>
Run Code Online (Sandbox Code Playgroud)
但它应该是这样的:
<dl>
<dt>key1</dt>
<dd>value1</dd>
<dt>key2</dt>
<dd>value2</dd>
</dl>
Run Code Online (Sandbox Code Playgroud)
我已经做了相当多的谷歌搜索,没有回答这个问题,至少不是在v5中工作的方式,或者不是有多个dt/dd对.
这似乎是d3.js应该能做的基本事情.
在您的解决方案:
x.append('dt')
.text(d=>d[0]);
x.append('dd')
.text(d=>d[1]);
Run Code Online (Sandbox Code Playgroud)
附加enter().append()循环的所有元素将按照它们的附加顺序附加到父级,对于您运行的顺序如下:首先是所有dts,然后是所有dds,如您所见.由enter语句创建的占位符节点(这些不是附加元素)不会以您可能期望的方式嵌套子节点.
尽管d3不包括使用方法实现selection.append()所需内容的方法,只需简单的方法,但使用标准d3方法和额外的一两步可以很容易地实现所需的行为.或者,我们可以自己将该功能构建到d3.selection中.
对于我的回答,我将完成一个使用您的数据结构并输入模式的示例,但是首先我将简化嵌套 - 而不是嵌套的附加,我只是演示了几种可能的方法来附加有序的兄弟.首先,我还简化了数据结构,但原理保持不变.
第一种方法可能是最直接的:使用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; })
})Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>Run Code Online (Sandbox Code Playgroud)
但是,也许更优雅的选择是挖掘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());
}
Run Code Online (Sandbox Code Playgroud)
它选择每个节点,在指定类型中创建一个新的配对兄弟节点(每个节点紧接在DOM中的原始节点之后),然后将新节点放在d3选择中并绑定数据.这允许您将方法链接到它上以设置元素的样式等,并允许您访问绑定的基准.请参阅下面的操作:
// 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 siblingsRun Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>Run Code Online (Sandbox Code Playgroud)
当然,将兄弟姐妹分开选择是很明智的,这样你就可以管理每个兄弟姐妹的更新/进入/退出等.
这个方法非常容易应用于您的示例,这是一个嵌套的解决方案,使用的结构与您期望的结果和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]; })Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
105 次 |
| 最近记录: |