Build a bottom axis
In the previous lesson we learnt how to manage margins efficiently on our chart.
Now, let's see how we can actually create a component that draws a bottom axis!
Re-usable Bottom Axis component
The code snippet below builds a AxisBottom
component. It is very much inspired from this blogpost by Amelia Wattenberger. I've just changed a few things, notably passing a scale as input instead of a range and a domain.
The logic mainly relies on the ticks()
method of a d3 scale. It takes a target number of ticks as input, find the most appropriate way to build smart ticks based on this target, and returns an array with all the tick positions.
What follows is just some svg drawings based on those tick positions.
const TICK_LENGTH = 6;
export const AxisBottom = ({ xScale, pixelsPerTick }) => {
const range = xScale.range();
const ticks = useMemo(() => {
const width = range[1] - range[0];
const numberOfTicksTarget = Math.floor(width / pixelsPerTick);
return xScale.ticks(numberOfTicksTarget).map((value) => ({
value,
xOffset: xScale(value),
}));
}, [xScale]);
return (
<>
{/* Main horizontal line */}
<path
d={["M", range[0], 0, "L", range[1], 0].join(" ")}
fill="none"
stroke="currentColor"
/>
{/* Ticks and labels */}
{ticks.map(({ value, xOffset }) => (
<g key={value} transform={`translate(${xOffset}, 0)`}>
<line y2={TICK_LENGTH} stroke="currentColor" />
<text
key={value}
style={{
fontSize: "10px",
textAnchor: "middle",
transform: "translateY(20px)",
}}
>
{value}
</text>
</g>
))}
</>
);
};
Using the component
Once you have the bottom and left axis component described above you just need to call them properly. You need to compute the bounds area by substracting the margins to the total svg area.
Don't forget to add an additional translation to the bottom axis to render it... at the bottom.
This axis is rendered without using d3.js to render.