使用d3.js实现带箭头连线的串联文本框的问题求解
问题原因与修复方案
1. 文本框为黑色且无文字显示
- rect元素默认填充色为黑色,且本身不支持渲染文本,需单独添加
text元素承载文字,同时可手动修改rect的填充、描边样式调整外观。 - 原代码中将
font-size属性写在rect上无效,该属性需要设置在text元素上。
2. 预期渲染5个盒子仅显示4个
- 原代码在绑定数据前,已经提前向svg内append了1个空的g元素,后续
selectAll('g')会选中这个已存在的g,5条数据匹配到1个已有元素后,enter阶段仅会新增4个g,因此少渲染1个盒子。 - 解决方案:删除提前append的无用空g,或给业务g添加专属类名做精准选择,避免选中无关元素。
3. 添加箭头连线连接各文本框
- 先通过svg的
marker元素定义箭头样式,再批量生成line元素,将前一个文本框的右侧坐标与后一个文本框的左侧坐标连接,给line设置marker-end属性绑定定义好的箭头即可。
完整可运行代码
HTML部分
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
JS部分
test() function test() { var data = ["a","b","c","d","e"] const width = 800 const height = 600 const margin = {left:10, right:10, top:10, bottom:10} const boxWidth = 30 const boxHeight = 30 const gap = 70 // 两个盒子之间的间距 var svg = d3.select("body").append("svg") .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom) .style("border","5px solid red"); // 定义箭头标记 svg.append("defs").append("marker") .attr("id", "arrow") .attr("viewBox", "0 0 10 10") .attr("refX", 8) // 箭头附着点的x坐标 .attr("refY", 5) .attr("markerWidth", 6) .attr("markerHeight", 6) .attr("orient", "auto") .append("path") .attr("d", "M 0 0 L 10 5 L 0 10 z") .attr("fill", "#333"); // 绑定数据生成g,仅选中带专属类的元素避免冲突 var group = svg.selectAll('.box-group') .data(data).enter() .append('g') .attr('class', 'box-group') .attr('transform',function(d,i) { return `translate(${margin.left + i*(boxWidth + gap)}, ${margin.top + 20})`; }); // 绘制矩形 group.append("rect") .attr("width", boxWidth) .attr("height", boxHeight) .attr("fill", "#fff") .attr("stroke", "#333") .attr("rx", 4) // 可选圆角 // 绘制文本 group.append("text") .attr("x", boxWidth/2) .attr("y", boxHeight/2) .attr("text-anchor", "middle") .attr("dominant-baseline", "middle") .attr("font-size", 14) .text(d => d) // 绘制带箭头的连接线 for(let i=0; i<data.length-1; i++) { const startX = margin.left + i*(boxWidth + gap) + boxWidth const startY = margin.top + 20 + boxHeight/2 const endX = margin.left + (i+1)*(boxWidth + gap) const endY = startY svg.append("line") .attr("x1", startX) .attr("y1", startY) .attr("x2", endX) .attr("y2", endY) .attr("stroke", "#333") .attr("marker-end", "url(#arrow)") } }
内容的提问来源于stack exchange,提问作者lucky1928
相关产品推荐
相关产品推荐

