如何在d3中输入2d数据,并访问每个子数组的句柄来操作其元素



比方说,我有一个2darr = [[1,2,3],[100,200],['A','B'...'Z']]。如您所见,arr[0].length!=arr[1].length!=arr[2].length

我想将它们重新发送为svg中的文本标记。

此外,我想灵活地处理每个子数组从(x,y(开始的位置,以及子数组(x,y(的每个元素之间的空间有多宽。

d3.select('svg').selectAll('g').data(arr).enter().append('g').selectAll('text').data((d)=>d).enter().append('text').text(d=>d)

但通过这种方式,我在每个g中都丢失了信息。我尝试在.selectAll('text'(之前设置.attr('x',(d,I(=>(I+1(*20(,但它只将'x'-attr添加到g中,对页面上显示的文本(即数组元素(没有影响。

问题是我把它们都放进了DOM中。但是,我如何在一个组(没有硬编码(中像在行中一样调整它们的.attr('x'(、.attr?

您可以尝试使用"getBBox"或getBoundingClientRect来获取节点宽度,然后进行继承布局。

var arr = [[1,2,3],[100,200],['A','B', 'C', 'D', 'E', 'Z']]
var container = d3.select("#box")
.append("g")
.attr("transform", "translate(10, 50)");
container
.selectAll("text")
.data(arr)
.enter()
.append("text")
.text(d => d);
/*
Using "getBBox" or "getBoundingClientRect" method to get each text node's width,
then move them one another.
You must make sure the svg element and its parent elements are visible,
which means "display: none" is should not applied on them.
*/
var xInit = 0, padding = 15;
container
.selectAll("text")
.each(function (d, i) {
d3.select(this).attr("x", xInit);
xInit += this.getBBox().width + padding;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="box" width="500" height="300"></svg>

我想我已经得到了。不确定这是否是一个明确的解决方案,但它有效。首先,在创建gs后添加id。然后根据id(即行(编写x和y坐标的函数。

function x(d,i,j){
let node_id = j[0].parentNode.id; // allows to dynamically access the ids of every text element
//calculate x_value here
return x_value;
}

并且该函数可以传递到原始链中。

d3.select('svg').selectAll('g').data(arr).enter().append('g')
.attr('id', (d,i)=>i) // adding ids to every g based on the array index
.selectAll('text').data((d)=>d).enter().append('text').text(d=>d)
.attr('x', x) // here

如果有人知道一个更精简的解决方案,我将不胜感激,因为我是Javascript和d3的新手。

最新更新