D3选择和输入

D3 selection and entry

本文关键字:输入 选择 D3      更新时间:2023-09-26

我试图通过首先选择使用唯一标识符的标签来创建d3.js元素,在这种情况下为"mydat"。然而,下面的代码没有给我任何东西。

<body>
<div id="mydat"></div>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
for (i=0; i<5; i++) {
d3.select("body").select("#mydat")
    .data(i.toString())
    .enter()
    .append("div")
    .text(String)
}
</script>
</body>
另一方面,如果我使用
d3.select("body").select("div")

并删除第一个

<div id="mydat"></div>

则得到

<div>1</div><div>2</div>

等。我很困惑。为什么第一种选择方法,即

d3.select("body").select("#mydat")

识别现有的'div'标签并将子'div'标签放在里面?此外,为什么选择的第二种方法不工作,如果我不删除现有的'div id="mydat"'?谢谢。

正确的做法是

var data = d3.range(0,5);
d3.select("body").select("#mydat")
    .selectAll("div")
    .data(data)
    .enter()
    .append("div")
    .text(function(d) { return d; })

你遇到的行为是代码中两个错误的混合。

第一个问题是.data()应该接受数据数组,字符串可以被视为字符数组,因此d3将字符串分解为字符。对于0 <= i < 5,这并不明显,但是如果您将i更改为两位数,您将看到divs看起来像这样:

<div>1</div> //10
<div>0</div>
<div>1</div> //11
<div>1</div>
<div>1</div> //12
<div>2</div>

解决方法是删除循环,并传入一个数据数组。循环在d3中很少见,因为它有很多强大的功能可以同时操作一组元素。

第二个问题,也是你的选择没有像预期的那样工作的原因,与父元素有关。

输入的实现。然后对Select进行专门化,使节点插入到组的父级,替换占位符。这这就是为什么呼叫选择很重要。在数据之前选择Join:为输入元素建立父节点。

来源:Mike Bostock对选段的解释

基本上,append将把元素插入当前选择的父节点的元素中。因为当前的选择从来没有selectAll设置的父节点,所以你会遇到父节点的奇怪行为。始终使用selectAll显式设置父节点。

在这种情况下,d3不需要循环。

试题:

var data = d3.range(0,5);
var sel = d3.select("#mydat").selectAll("div.mydatItem").data(data);
sel.enter().append("div").attr("class", "mydatItem");
sel.text(function(d) { return d;};

这将创建:

<div id="mydat">
    <div class="mydatItem">0</div>
    <div class="mydatItem">1</div>
    <div class="mydatItem">2</div>
    <div class="mydatItem">3</div>
    <div class="mydatItem">4</div>
</div>

select只选择一个元素,而selectall将选择所有匹配的元素。也就是说,select("div")将选择它找到的第一个div,而selectAll("div")将选择每个div。

我不完全清楚为什么你会得到你看到的输出,但是你的".data()"调用应该传递一个数据数组。您通常将非数组项传递为" data([item]) "。

试试这个:

d3.select('#mydat') 

而不是

   d3.select('body').select('#mydat')