How to hierarchically append "composed" elements based on elements' attributes using D3 d3js?
我正在使用 D3.js,并且我有一个元素列表,其中包含一个描述如下类别的属性:
1 2 3 4 | var nodes = [ {id:"a", cat:[0,1]}, {id:"b", cat:[0]}, {id:"c", cat:[0,1,2]}]; |
每个元素都是由强制布局定位的多圆节点。一个元素的类别数定义了代表它的圆圈数。
我现在的"解决方案"是为每个类别创建图层。强制布局处理数据列表。这些层处理 svg 元素。
每一层都是一个元素。
-
在
<g class="layer2"> 中,我为节点 c 画了一个圆,半径 = 9; -
在
<g class="layer1"> 中,我为节点 a 和 c 绘制圆,半径 = 6; -
在
<g class="layer0"> 中,我为节点 a、b 和 c 绘制圆,半径 = 3;
问题是每个数据元素都由分离层中的分离圆圈表示。
我们如何用一组圆圈来表示每个元素,如下所示:
1 2 3 4 5 6 7 8 9 | <g class="node" id="a"> <circle>... <circle>... </g> <g class="node" id="b"> <circle>... </g> <g class="node" id="c"> <circle>... <circle>... <circle>... </g> |
是否可以在 D3 代码风格中分层使用某些东西,例如:
1 2 3 4 5 6 7 8 | svg.selectAll(".node") .data(nodes) .enter() .append("g") .attr("id", function(d){return d.id;} //for each category on this node .append("circle") .attr("r", function(){ return (cat+1)*3;}); |
这样的解决方案将是最好的选择。
或者我必须单独创建元素
在我看来你只需要嵌套选择:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var groups = svg.selectAll(null) .data(nodes) .enter() .append("g") .attr("id", function(d) { return d.id }); var circles = groups.selectAll(null) .data(function(d) { return d.cat }) .enter() .append("circle") //etc... |
这是一个演示,其中包含您的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | var nodes = [{ id:"a", cat: [0, 1] }, { id:"b", cat: [0] }, { id:"c", cat: [0, 1, 2] }]; var colors = d3.scaleOrdinal(d3.schemeCategory10); var svg = d3.select("svg"); var groups = svg.selectAll(null) .data(nodes) .enter() .append("g") .attr("id", function(d) { return d.id }) .attr("transform", function(d, i) { return"translate(" + (50 + 100 * i) +",75)"; }); var circles = groups.selectAll(null) .data(function(d) { return d.cat }) .enter() .append("circle") .attr("r", function(d) { return 10 + (d * 10) }) .style("fill", function(d, i) { return colors(i) }); circles.sort(function(a, b) { return d3.descending(a, b) }) |
1 2 | <script src="https://d3js.org/d3.v4.min.js"> <svg></svg> |
如果你检查你的 SVG,你会看到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <svg> <g id="a" transform="translate(50,75)"> <circle r="30" style="fill: rgb(31, 119, 180);"></circle> <circle r="20" style="fill: rgb(255, 127, 14);"></circle> </g> <g id="b" transform="translate(150,75)"> <circle r="30" style="fill: rgb(31, 119, 180);"></circle> </g> <g id="c" transform="translate(250,75)"> <circle r="30" style="fill: rgb(31, 119, 180);"></circle> <circle r="20" style="fill: rgb(255, 127, 14);"></circle> <circle r="10" style="fill: rgb(44, 160, 44);"></circle> </g> </svg> |
PS:我正在对圆圈进行排序(查看代码的底部)以将较小的圆圈置于顶部,使它们可见。
你可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 | svg.selectAll(".node") .data(nodes) .enter() .append("g") .attr("id", function(d){return d.id;}) .selectAll("circle") .data(function(d) {return d.cat}) // <-- bind cat data .enter() .append("circle") .attr("r", function(d) { //set radius }); |