gpt4 book ai didi

javascript - d3.js:将数据绑定(bind)到现有的 svg。 selector.each 是做什么的?

转载 作者:行者123 更新时间:2023-11-29 14:57:39 25 4
gpt4 key购买 nike

我在 html 页面上有一些 svg。我想在它们上面绑定(bind)一些数据,并根据该数据添加装饰元素。我认为我必须做的是:

// pseudo-code
selection = select all existing svg piece i want to decorate

var datas = selection.each( function(d,i) { // each is right? maybe selection.datum() is better?
var data = this.(do something with the svg piece)
return data;
});

// add elements with the "default" chain selection.data(datas).enter().append()

我注意到 selection.each 没有返回我可以找到返回数据的东西。我认为这是方式,但我无法弄清楚我必须做什么才能看到绑定(bind)数据。

所以我必须做一些肮脏的解决方法,比如:

var datas = [];
selection.each( function(d,i) { // each is right? maybe selection.datum() is better?
var data = this.(do something with the svg piece)
datas.push(data);
});

为什么?我如何在不将数据手动推送到数组并将数据绑定(bind)到某些现有 svg 元素内的情况下做类似的事情?

这是一个jsFiddle example .

或者,如果您愿意,代码:

html:

<div id="container">
<svg>
<rect id="0" x="0" y="50" width="30" height="30"/>
<rect id="1" x="50" y="50" width="30" height="30"/>
<rect id="2" x="100" y="50" width="30" height="30"/>
<rect id="3" x="150" y="50" width="30" height="30"/>
<rect id="4" x="200" y="50" width="30" height="30"/>
<rect id="5" x="250" y="50" width="30" height="30"/>
</svg>
</div>

js:

var svg = d3.select("#container svg"); 
var districts = svg.selectAll("rect");

var district_data = [];
var _c = districts.each(function(d, i) {
var bbox = this.getBBox();
var centroid = [
bbox.x + bbox.width/2,
bbox.y + bbox.height/2
];
var ret = {centroid:centroid, position:bbox.x};
district_data.push( ret );
return ret;
});

// now, i'm expecting that _c should be something
// similar to district_data
console.log(_c);

svg
.selectAll("circle")
.data(district_data) // i think i should use `_c` instead of manually created `district_data` but does not work
.enter()
.append("circle")
.attr("class", "district_circle")
.attr("cx", function(d){ return d.centroid[0]})
.attr("cy", function(d){ return d.centroid[1]})
.attr("r", 10)
.attr("fill", function(d){ return "rgb("+d.position+",0,0)"});

最佳答案

首先,期望 each() 方法返回数据数组是不正确的。这只是一种迭代选择的方法。它返回的(分配给 _c 的东西)是一个 d3 选择对象——与您调用 each() 的选择对象相同。 IE。 _c == districts 计算结果为真。 AFAIK,d3 选择对象不提供任何可用于按照您描述的方式收集值的内容。

通常,您希望使用 .map() 函数来收集这些值并将它们分配给 _c,但不幸的是,这似乎不是在这里可能,因为 districts 是 d3 选择,而不是平面数组。而且,如果您尝试对其调用 map(),我认为它实际上不会遍历选择中的每个元素,并且您还会遇到 js 错误,因为 this 对象未分配给您需要对其调用 getBBox() 的 SVG 元素。

最重要的是,我认为您采用的方法是正确的:使用 each() 进行迭代并通过插入数组来构建数组。


我可以建议另一种更简洁的方法,但它需要修改现有 SVG 的结构:

不是让 rects 成为兄弟,而是将每个都嵌套在 g 中。喜欢:

<div id="container">
<svg>
<g>
<rect id="0" x="0" y="50" width="30" height="30"/>
</g>
<g>
<rect id="1" x="50" y="50" width="30" height="30"/>
</g>
...

然后在 JS 中(未经测试):

svg.selectAll('g')
.each(function(d, i) { // Note, d is actually undefined, bc no data-binding was done
var rect = d3.select(this).select('rect');
var bbox = this.getBBox();
var centroid = [
bbox.x + bbox.width/2,
bbox.y + bbox.height/2
];

// Now create the circle, appending it to the group,
// as a sibling of its corresponding rect
var circle = d3.select(this).append('circle')
.attr("class", "district_circle")
.attr("cx", centroid[0])
.attr("cy", centroid[1])
.attr("r", 10)
.attr("fill", "rgb("+bbox.x+",0,0)");
});

这仍然不是很好的形式,因为定位应用于每个圆和矩形,而理想情况下,定位将应用于组级别——这并不难实现。但现在我们变得挑剔了。

关于javascript - d3.js:将数据绑定(bind)到现有的 svg。 selector.each 是做什么的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15292944/

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