You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte结合D3实现柱状图时svg下g元素transform变换异常问题

问题修复方案

错误点说明

  • SVG的translate变换不需要加px单位,加单位会导致浏览器解析异常,变换不生效。
  • <g>是SVG的纯分组容器,本身不支持width和height属性,设置这两个值没有任何作用,它的边界范围天生由内部子元素的总大小决定,无法手动固定,这是SVG规范定义的正常特性。
  • 柱子的x坐标计算有误:d3.scaleBand()返回的x值本身就是每个柱子的左边缘坐标,额外加上xScale.bandwidth() / 2会让所有柱子整体右偏移半个带宽,最终超出容器边界,看起来就像<g>的位置不对。

修正后代码

<script>
  import * as d3 from 'd3';
  let data = [
    { name: 'Apple', amount: 20 },
    { name: 'Orange', amount: 80 },
    { name: 'Banana', amount: 50 },
    { name: 'Grapes', amount: 10 },
  ];

  let width = 600;
  let height = 400;

  let margins = { top: 20, right: 20, bottom: 100, left: 100 };

  let innerWidth = width - margins.left - margins.right;
  let innerHeight = height - margins.top - margins.bottom;

  const xScale = d3
    .scaleBand()
    .domain(data.map((d) => d.name))
    .range([0, innerWidth])
    .paddingInner(0.1)
    .paddingOuter(0.1);
  const yScale = d3
    .scaleLinear()
    .domain([0, d3.max(data, (d) => d.amount)])
    .range([innerHeight, 0]);
</script>

<div class="canvas">
  <svg {width} {height}>
    <g transform={`translate(${margins.left}, ${margins.top})`}>
      {#each data as d}
        <rect
          width={xScale.bandwidth()}
          height={innerHeight - yScale(d.amount)}
          x={xScale(d.name)}
          y={yScale(d.amount)}
          fill="#3385ff"
        />
      {/each}
    </g>
  </svg>
</div>

<style>
  .canvas {
    margin-top: 100px;
    width: 600px;
    height: 400px;
    background-color: #fff;
  }
</style>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:57:02