我尝试使用d3.js创建元素,首先使用唯一标识符选择标记,在本例中为#34; 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")
识别现有的&#39; div&#39;标记并放置孩子&#39; div&#39;里面的标签?另外,如果我不删除现有的&#39; div id =&#34; mydat&#34;&#39 ;?,为什么第二种选择方法不起作用?感谢。
答案 0 :(得分:2)
正确的做法是
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中是罕见的,因为它具有许多强大的功能,可以同时对元素组进行操作。
第二个问题,以及您的选择未按预期工作的原因,与父元素有关。
然后将enter.select的实现专门化为节点 插入到组的父级中,替换占位符。这个 这就是为什么在数据之前调用selection.selectAll是至关重要的 join:它建立父节点以输入元素。
Source: Mike Bostock's explanation of selections
基本上,append
会将元素插入到当前选择的父节点的元素中。由于当前选择从未使用selectAll
设置父级,因此您将遇到父节点的奇怪行为。始终使用selectAll
显式设置父节点。
答案 1 :(得分:1)
在这种情况下,您不需要使用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])
”传递。
答案 2 :(得分:-2)
请改为尝试:
d3.select('#mydat')
而不是
d3.select('body').select('#mydat')