I am trying d3.js with svelte, and I started to do a simple bar chart, but I am facing an issue I couldn't figure out. The issue, is, the group element g
inside the svg
element, that contains the bars, is initially shifted from the origin of the svg
element (the top left corner). This is the code
<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);
const yScale = d3
.scaleLinear()
.domain([0, d3.max(data, (d) => d.amount)])
.range([innerHeight, 0]);
</script>
<div class="canvas">
<svg {width} {height}>
<g>
{#each data as d}
<rect
width={xScale.bandwidth()}
height={innerHeight - yScale(d.amount)}
x={xScale(d.name) xScale.bandwidth() / 2}
y={yScale(d.amount)}
/>
{/each}
</g>
</svg>
</div>
<style>
.canvas {
margin-top: 100px;
width: 600px;
height: 400px;
background-color: #fff;
}
</style>
I was expecting the group element g
to start at (0,0)
of the svg
element (the top left corner), but it's x-shifted without any transform
attribute on the g
element. This is messing things up when I try to shift the group element appropriately to add axes later. My question is: why is there initial shift?
Here are the svg
and g
elements as appear on the screen
CodePudding user response:
Your g
is not translated, the bounds of the g
merely reflect the bounds of its contents. If the contents aren't bounded by a point at [0,0], the g
also won't be bounded by a point at [0,0].
Eyeballing it, I'd say the left most limit of the bars, and therefore the g
, is about half the bandwidth from the edge of the SVG. If we look at how you position the bars, that makes sense:
x={xScale(d.name) xScale.bandwidth() / 2}
Despite a scaled value of 0 for the first bar, the rectangle is nudged over by half the bandwidth. The placement of the g
just reflects the placement of the bars, not a transform.