【发布时间】:2024-04-13 12:15:02
【问题描述】:
重新认识 hos D3JS 工作,尤其是 .selectAll/.data/.enter;学习如何嵌套数据。
我有这个工作演示:
svg = d3.select('body')
.append('svg')
.attr('width', 640)
.attr('height', 480);
svg.selectAll('text')
.data( [ 'hello', 'world' ] )
.enter()
.append('text')
.attr('x', 10)
.attr('y', function( d, i ) {
return 20 + i * 20;
})
.selectAll('tspan')
.data( function( d, i ) { // d is from the first data
return Array.from(d); // if needed, could return an array or object that includes the initial value, too.
})
.enter()
.append('tspan')
.attr('class', function( d, i ) {
console.log( 'tspan class:', d, i );
if ( ['a', 'e', 'i', 'o', 'u', 'y'].includes(d) ) {
return 'vowel';
}
})
.text( function( d, i, foo ) { // d is from the second data
console.log( 'tspan text:', d, i, /*foo*/ );
return d;
})
.exit()
.attr('class', 'strong') // this will set strong on <tspan>, but I wanted it on <text>
;
(在 Codepen 上查看:D3JS selectAll SVG nested。)
注意我们有两个data(),第二个(用于<tspan>s)嵌套在第一个(用于<text>s)中。
我正在尝试做的事情:
- 我想在
<text>上设置strong类属性。 - 我认为
exit()会让我脱离使用 tspan 的“范围”/巢穴……但我错了。 - 如果我注释掉
exit(),那么在<tspan>s 上设置强类属性...而我希望在父<text>上设置它!
除此之外,我怎样才能做到这一点:
- 将队列向上移动(在第二个
data()之前)。 - 使用单独的语句 (
svg.selectAll('text').attr('class', 'strong');)
我可以使用这两个选项之一,在这个例子中它是微不足道的......
但是我想知道是否有可能摆脱嵌套选择,如果可以,如何?
我希望这已经足够清楚了;如果不是,请发表评论,我会澄清:)
【问题讨论】:
-
我尝试了很多东西,但如果不使用变通方法、黑客、反模式或您提到的两种解决方案,这似乎是不可能的。
-
无论好坏,我意识到两年前我问过同样的问题:D3JS: appending simple nested HTML in a single command。简短的回答是:“不,你不能摆脱嵌套。”但是,您可以使用变量来分解代码并保持其可读性;见this answer,特别是最后一个代码sn-p。
标签: javascript d3.js svg