我正在使用D3.js,我有一个元素列表,其中的属性描述了类似这样的类别:
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; 问题是每个数据元素都由分隔层中的分隔圆圈表示。
我们如何通过这样的一组圆圈来表示每个元素:
<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风格的代码中使用层次结构的东西,如:
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;});
这样的解决方案是最佳选择。
或者我是否必须单独创建元素<g class="node" id="...">
,selectAll(".node")
然后将它们链接到数据(节点列表)?
答案 0 :(得分:3)
在我看来,您只需要嵌套选择:
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...
这是一个使用nodes
数据显示它的演示:
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)
})
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
如果你检查你的SVG,你会看到这个:
<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 :(得分:0)
你可以这样做:
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
});