gpt4 book ai didi

javascript - 如何摆脱D3JS中嵌套的selectAll?

转载 作者:行者123 更新时间:2023-11-28 03:09:46 25 4
gpt4 key购买 nike

重新熟悉 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)内。

我正在尝试做的事情:

  • 我想设置 strong <text> 上的类属性
  • 我想exit()会让我脱离使用 tspan 的“范围”/巢……但我错了。
  • 如果我注释掉exit() ,然后在 <tspan> 上设置强类属性s…而我想把它放在 parent 身上<text> !

除此之外,我怎样才能实现这一目标

  • 向上移动该行(在第二个 data() 之前)。
  • 使用单独的语句 ( svg.selectAll('text').attr('class', 'strong'); )

我可以使用这两个选项之一,在这个例子中这将是微不足道的......
但是我想知道是否可以退出嵌套选择,如果可以,如何退出?

我希望这已经足够清楚了;如果没有,请发表评论,我会澄清:)

最佳答案

您可以考虑修改原始数据,这样您就可以只使用一种数据绑定(bind)和一种更新模式。在该模式中,您可以检查/使用该单词,但也可以检查该单词的每个字母(您也可以稍后即时执行此操作):

const test_data = [ 'hello', 'world', 'wthtvwls' ];

const modified_data = test_data.map((item,index) => {
return {
word: item,
array: Array.from(item)
}
});

console.log(modified_data);

然后使用此数据(演示 - https://codepen.io/Alexander9111/pen/qBdZrLv ):

svg = d3.select('body')
.append('svg')
.attr('width', 640)
.attr('height', 480);
svg.selectAll('text')
.data( modified_data )
.enter()
.append('text')
.attr('x', 10)
.attr('y', function( d, i ) {
return 20 + i * 20;
})
.html(function(d) {
return d.letters.map((letter,index) => {
if (['a', 'e', 'i', 'o', 'u', 'y'].includes(letter)){
return '<tspan class="vowel">' + letter + '</tspan>';
} else{
return '<tspan>' + letter + '</tspan>';
}
}).join("");
})
.attr('class', function( d, i ) {
for (letter of d.letters){
console.log('letter', letter);
if (['a', 'e', 'i', 'o', 'u', 'y'].includes(letter)) {
return 'strong';
}
}
})
.exit();

注意 .html() 的使用函数然后 .map()在其中使用我们当前的 data.letters 在正常更新模式中添加 '<tspan class="vowel">''<tspan>' (无类元音)。

https://codepen.io/Alexander9111/pen/qBdZrLv

但我不确定您是否想要这样一个特定的用例或对嵌套更新模式的更通用的答案?如果是这样,那么这个 block 可能有帮助吗? -https://bl.ocks.org/mpbastos/bd1d6763d34ac5d3ce533a581b291364

更新 - 我意识到我第一次读错了问题

所以现在我很清楚,我的一次性解决方案并不比 @Fabien (OP) 建议的其他两个解决方案更有帮助(移动线路(在第二个 data() 之前)或使用单独的语句svg.selectAll('text').attr('class', 'strong');)

我尝试了以下模式:

svg.selectAll('text')
.data( test_data )
.enter()
.append('text')
.attr('x', 10)
...
.selectAll('tspan')
.data( ...)
.enter()
.append('tspan')
.attr('class', 'example')
.exit()
.select(this.ParentNode)
.attr('class', 'example')

还有.select(this.ParentNode)之前.exit()但都不起作用。

唯一有效的方法,但它也是一种解决方法,并且可能是一种反模式,那就是 - 劫持 attr 函数以“抓取”嵌套更新之外的父级:

svg = d3.select('body')
.append('svg')
.attr('width', 640)
.attr('height', 480);
text = svg.selectAll('text')
.data( test_data )
.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(1, i, this.parentNode);
//hijack the attr function to "grab" parent outside nested update pattern
if (i == 0) {
d3.select(this.parentNode).attr('class', 'strong');
}
//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();

这也不是一个完美的解决方案。

我认为因为一旦.data()在选择上调用函数,它现在不再是一个普通的节点列表对象,并且 .exit()函数仅设计为在一层深度使用。

我认为OP概述的两种解决方案是最好的,但我希望被证明是错误的!

关于javascript - 如何摆脱D3JS中嵌套的selectAll?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60240915/

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