D3.js堆叠柱状图:将rect内text元素移动至父级g节点下
问题原因
SVG 标准中 <rect> 属于不可嵌套子元素的图形标签,原有代码通过 vLayer.selectAll("rect").append("text") 的写法,会将 <text> 作为 <rect> 的子节点插入,既不符合SVG语法导致标签无法正常渲染,也不满足预期的DOM层级要求。
修正方案
不要选中已生成的rect后追加text,直接在每个layer对应的<g>容器下,绑定和rect完全一致的数据集,单独创建text元素,和rect保持同级关系即可。修正后的代码如下:
var vLayer = svg .selectAll(".layer") .data(layers) .enter() .join("g") .attr("class", "layer") .attr("fill", (layer) => colors[layer.key]) // 绘制堆叠矩形,逻辑和原有代码保持一致 vLayer.selectAll("rect") .data((layer) => layer) .join("rect") .attr("class", "rec") .attr("id", (sequence) => sequence.data.name) .attr( "x", (sequence) => x0Scale(sequence.data.name) ) .attr("width", x0Scale.bandwidth()) .attr("y", (sequence) => yScale(sequence[1])) .attr("height", (sequence) => yScale(sequence[0]) - yScale(sequence[1])) // 直接在g容器下创建text,和rect为同级节点,绑定相同的数据集 vLayer.selectAll("text") .data((layer) => layer) .join("text") .style("text-anchor", "middle") .style("font-size", "26px") .style("font-family", "poppins_regular") .style("font-weight", "bold") .style("fill", "white") // 同步修正坐标逻辑:x取矩形水平中点,y取矩形垂直中点,保证标签在对应堆叠块内部居中 .attr("x", (sequence) => x0Scale(sequence.data.name) + x0Scale.bandwidth() / 2) .attr("y", (sequence) => (yScale(sequence[0]) + yScale(sequence[1])) / 2) .text(function (data, i) { return "some text"; });
实现效果
修正后每个layer的g容器内,rect和对应的text为同级节点,DOM结构符合预期:
<g class="layer" fill="#ff7f50"> <rect class="rec" id="24-May-2022 02:46 PM (EST)" x="91.14" width="106.99" y="320" height="80"></rect> <text x="144.64" y="360">Some Text</text> <rect class="rec" id="30-Apr-2022 12:00 AM (EST)" x="289.28" width="106.99" y="294.73" height="105.26"></rect> <text x="342.78" y="347.36">Some Text</text> <!-- 其余矩形和对应标签结构一致 --> </g>
- 若之前运行旧代码已经生成了嵌套在rect内的无效text节点,刷新页面重新运行修正后代码即可,D3的join逻辑会自动生成正确的DOM结构,无需手动清理旧节点。
- SVG元素按代码顺序渲染,后渲染的元素会覆盖在先渲染元素上方,先绘制rect再绘制text的顺序,可以保证文字标签显示在色块上层,不会被矩形遮挡。
内容的提问来源于stack exchange,提问作者C Sharper
相关产品推荐
相关产品推荐

