我在D3.js中的enter()
选项中添加了一个元素和一个子元素:
let data = [ 1, 2, 3 ];
selection.data( data ).append( 'g' )
.attr( 'name', d => d )
.append( 'text' )
.text( d => d );
这会按预期创建一些元素:
<g name="1"><text>1</text></g>
<g name="2"><text>2</text></g>
<g name="3"><text>3</text></g>
加载新数据时,g
元素会收到它,但text
元素仍然绑定到以前的数据:
let data = [ 'A', 'B', 'C' ];
selection.attr( 'name', d => d )
.selectAll( 'text' )
.text( d => `[${d}]` ); // <- Remains unchanged
结果 - 1,2,3不应再存在:
<g name="A"><text>1</text></g>
<g name="B"><text>2</text></g>
<g name="C"><text>3</text></g>
如何正确使用D3,以便text
元素也会收到新数据?
答案 0 :(得分:1)
执行此操作的一种方法是将<g>
与<text>
分开。然后您可以单独重新绑定数据:
// Set up an SVG already in the document
var svg = d3.select('svg');
// Create the groups with data bound to them
var data = [ 1, 2, 3 ];
var gs = svg.selectAll('g')
.data( data ).enter()
.append( 'g' )
.attr( 'name', String);
// Add text as children to each group, with the data passed through
var text = gs.append( 'text' ).text(String);
// Update the data and attributes/text for each
data = [ 'A', 'B', 'C' ];
gs.data( data ).attr( 'name', String )
text.data( data ).text( function(d){ return `[${d}]`; });
这给了我以下内容:
请注意,我必须稍微修改您的代码以获得完整的示例。
答案 1 :(得分:1)
(这只是一个旁注,comments中的@LarsKotthoff答案是正确的答案)
您可以使用this.parentNode-__data__
访问父节点的数据(在本例中为group元素),并保留selectAll
。
例如,这个:
var svg = d3.select("body").append("svg");
var data = [ 1, 2, 3 ];
var groups = svg.selectAll(".groups").data(data);
groups.enter().append('g')
.attr('name', (d) => d )
.append('text')
.text((d)=> d );
会给你:
<g name="1"><text>1</text></g>
<g name="2"><text>2</text></g>
<g name="3"><text>3</text></g>
但是如果您更改数据并将其再次绑定到组,则可以使用this.parentNode.__data__
获取其子组(文本元素)中相应组的数据。
因此,这个:
var data = [ 'A', 'B', 'C' ];
groups.data(data).attr( 'name', (d) => d )
.selectAll('text')
.text(function(){ return this.parentNode.__data__});
现在会给你:
<g name="A"><text>A</text></g>
<g name="B"><text>B</text></g>
<g name="C"><text>C</text></g>
请注意,由于代码使用this
,我们无法在此处使用胖箭头功能。
查看演示:
var svg = d3.select("body").append("svg");
var data = [1, 2, 3];
var groups = svg.selectAll(".groups").data(data);
groups.enter().append('g')
.attr('name', (d) => d)
.append('text')
.text((d) => d);
var firstSVG = (new XMLSerializer()).serializeToString(svg.node());
var data = ['A', 'B', 'C'];
groups.data(data).attr('name', (d) => d).selectAll('text')
.text(function() {
return this.parentNode.__data__
});
var secondSVG = (new XMLSerializer()).serializeToString(svg.node());
console.log("First SVG:" + firstSVG)
console.log("Second SVG:" + secondSVG)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
答案 2 :(得分:1)
更新时,您只需使用.select("text")
代替.selectAll("text")
即可使其正常运行。两者之间的区别在于.select()
使用父元素的数据更新绑定到所选元素的数据,而.selectAll()
则不会。由于每text
只有一个g
元素,.select()
就足够了。