You need to enable JavaScript to run this app. D3.js中坐标轴刻度置于图表内部时如何为刻度标签添加SVG矩形背景
优惠活动
大模型
产品
解决方案
定价
更多

D3.js中坐标轴刻度置于图表内部时如何为刻度标签添加SVG矩形背景

实现方法

要给内置的刻度标签加白色背景,只需要在D3生成的每个.tick分组内,在刻度线和文本标签之间插入背景矩形即可,矩形尺寸通过获取文本实际宽高动态计算,保证完全覆盖标签下方的刻度线。

示例图

核心修改说明

  1. 先修正CSS的text-anchor属性错误:将原text-anchor: center改为text-anchor: middle,避免文本位置偏移导致背景矩形定位不准。
  2. 每个坐标轴渲染完成后,遍历所有刻度节点,获取文本的尺寸信息,插入白色矩形:
// 以X轴为例,Y轴逻辑完全一致
.each(function() {
  // 拿到当前tick的容器节点
  const tickGroup = d3.select(this.parentNode);
  // 拿到当前刻度文本的DOM节点,获取实际宽高和位置
  const textNode = tickGroup.select("text").node();
  const textBbox = textNode.getBBox();
  // 背景内边距,可按需调整大小
  const bgPadding = 2;
  // 把矩形插入到刻度线和文本之间,保证渲染层级正确
  tickGroup.insert("rect", "text")
    .attr("fill", "#fff")
    .attr("x", textBbox.x - bgPadding)
    .attr("y", textBbox.y - bgPadding)
    .attr("width", textBbox.width + bgPadding * 2)
    .attr("height", textBbox.height + bgPadding * 2)
})

完整可运行代码

<!DOCTYPE html>
<html>
<head>
  <meta name="description" content="With 0 removal">
  <title>
    D3.js 刻度标签添加背景
  </title>
  <script type="text/javascript" src="https://d3js.org/d3.v5.min.js">
  </script>
  <style>
    svg text {
      fill: green;
      font: 15px sans-serif;
      text-anchor: middle;
    }
  </style>
</head>
<body>
  <script>
    var width = 400,
      height = 400;
    const margin = 5;
    const padding = 5;
    const adj = 30;
    var svg = d3.select("body")
      .append("svg")
      .attr("preserveAspectRatio", "xMinYMin meet")
      .attr("viewBox", "-" +
        adj + " -" +
        adj + " " +
        (width + adj * 3) + " " +
        (height + adj * 3))
      .style("padding", padding)
      .style("margin", margin)
      .attr("width", width)
      .attr("height", height);
    var xscale = d3.scaleLinear()
      .domain([0, 10])
      .range([0, width]);
    var yscale = d3.scaleLinear()
      .domain([0, 1])
      .range([height, 0]);
    var x_axis = d3.axisBottom(xscale)
      .tickSizeInner(-(height))
      .tickSizeOuter(0);

    // 处理X轴
    svg.append("g")
      .classed('axis axis-x', true)
      .attr("transform", "translate(0, " + height + ")")
      .call(x_axis)
      .selectAll(".tick text")
      .attr("transform", "translate(0,-20)")
      // 新增:X轴刻度加背景
      .each(function() {
        const tickGroup = d3.select(this.parentNode);
        const textNode = tickGroup.select("text").node();
        const textBbox = textNode.getBBox();
        const bgPadding = 2;
        tickGroup.insert("rect", "text")
          .attr("fill", "#fff")
          .attr("x", textBbox.x - bgPadding)
          .attr("y", textBbox.y - bgPadding)
          .attr("width", textBbox.width + bgPadding * 2)
          .attr("height", textBbox.height + bgPadding * 2)
      })

    svg.select('.axis-x')
      .selectAll('.tick')
      .each(function(d) {
        if (Number(d) === 0) {
          d3.select(this).remove();
        }
      })
    var y_axis = d3.axisLeft(yscale)
      .tickSize(-width);

    // 处理Y轴
    svg.append("g")
      .classed('axis axis-y', true)
      .call(y_axis)
      .selectAll(".tick text")
      .attr("transform", "translate(30,0)")
      // 新增:Y轴刻度加背景
      .each(function() {
        const tickGroup = d3.select(this.parentNode);
        const textNode = tickGroup.select("text").node();
        const textBbox = textNode.getBBox();
        const bgPadding = 2;
        tickGroup.insert("rect", "text")
          .attr("fill", "#fff")
          .attr("x", textBbox.x - bgPadding)
          .attr("y", textBbox.y - bgPadding)
          .attr("width", textBbox.width + bgPadding * 2)
          .attr("height", textBbox.height + bgPadding * 2)
      })

    svg.select('.axis-y')
      .selectAll('.tick')
      .each(function(d) {
        if (Number(d) === 0) {
          d3.select(this).remove();
        }
      })
  </script>
</body>
</html>

内容的提问来源于stack exchange,提问作者acharyaks90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 06:42:03