D3.js中如何根据性别动态追加rect或circle并设置对应属性
D3 动态生成不同形状节点的实现方案
原代码问题修正
现有代码存在两处核心问题:
- 节点选择逻辑错误:
selectAll("rect").selectAll("circle")是嵌套选择逻辑,不符合同级节点绑定的需求,应该改为通用类选择器占位 - append回调缺少返回值:动态创建元素的三元运算没有加
return,会导致元素创建失败
规范实现代码
var data = [ {"name": "Lincoln", "pid":1, "sex": "M"}, {"name": "Tad", "pid":2, "sex":"M"}, {"name": "Mary", "pid":3, "sex": "F"}, ]; // 通用节点配置,可自行调整尺寸 const RECT_WIDTH = 20; const RECT_HEIGHT = 20; const CIRCLE_RADIUS = 10; var nodes = svg.append("g") // 用通用类做占位选择,不指定元素类型 .selectAll(".person-node") .data(information.descendants()) .enter() // 动态创建元素,补充return返回元素名 .append(function(d){ return getPerson(d.data.child).sex === "M" ? "rect" : "circle" }) // 加通用类方便后续操作 .attr("class", "person-node") .attr("fill", "#69b3a2") // 遍历节点按性别设置对应属性 .each(function(d) { const person = getPerson(d.data.child); const node = d3.select(this); if (person.sex === "M") { // 男性矩形设置x、y、宽高,基于树布局的d.x、d.y做居中偏移 node .attr("x", d.x - RECT_WIDTH / 2) .attr("y", d.y - RECT_HEIGHT / 2) .attr("width", RECT_WIDTH) .attr("height", RECT_HEIGHT); } else { // 女性圆形设置cx、cy、半径 node .attr("cx", d.x) .attr("cy", d.y) .attr("r", CIRCLE_RADIUS); } });
可选简化写法
如果属性逻辑简单,也可以直接在attr的回调中做判断,省略each环节:
.append(function(d){ return getPerson(d.data.child).sex === "M" ? "rect" : "circle" }) .attr("class", "person-node") .attr("fill", "#69b3a2") .attr("x", d => getPerson(d.data.child).sex === "M" ? d.x - 10 : null) .attr("y", d => getPerson(d.data.child).sex === "M" ? d.y - 10 : null) .attr("width", d => getPerson(d.data.child).sex === "M" ? 20 : null) .attr("height", d => getPerson(d.data.child).sex === "M" ? 20 : null) .attr("cx", d => getPerson(d.data.child).sex === "F" ? d.x : null) .attr("cy", d => getPerson(d.data.child).sex === "F" ? d.y : null) .attr("r", d => getPerson(d.data.child).sex === "F" ? 10 : null)
D3会自动忽略值为null的属性设置,不会影响节点渲染。
内容的提问来源于stack exchange,提问作者djo
相关产品推荐
相关产品推荐

