✅ – Nesho – 10-41 Feb 25

Hello, I'm using d3 to render charts. I have a problem with generating an area with d3.area, the area is being generated outside of my svg size, even though I'm giving the y-scale the same size as my svg. Any ideas?
export function useD3Scales<T>({ data, xKey, yKey }: Options<T>) {
const { width, height, margin } = useResponsiveContainerSize();

const xScale = d3
.scaleTime()
.domain(
d3.extent(data, (d, i) => {
return xKey ? xKey(d) : i;
})
)
.range([margin.left, width - margin.right]);

const yScale = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d[yKey]))
.range([height - margin.bottom, margin.top]);

return { xScale, yScale };
}
export function useD3Scales<T>({ data, xKey, yKey }: Options<T>) {
const { width, height, margin } = useResponsiveContainerSize();

const xScale = d3
.scaleTime()
.domain(
d3.extent(data, (d, i) => {
return xKey ? xKey(d) : i;
})
)
.range([margin.left, width - margin.right]);

const yScale = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d[yKey]))
.range([height - margin.bottom, margin.top]);

return { xScale, yScale };
}
N
Nesho417d ago
The area component
export function Area<T>({
color = 'blue',
data,
dataKey,
line = true,
...rest
}: AreaProps<T>) {
const { xScale, yScale } = useD3Scales({
data,
yKey: dataKey,
});
const { theme } = useTheme();

console.log(yScale.range());

const areaGenerator = useMemo(() => {
return d3
.area<T>()
.x((_, i) => xScale(i))
.y0(yScale(0))
.y1((d) => yScale(d[dataKey]));
}, [yScale, xScale]);

const area = useMemo(() => areaGenerator(data), [areaGenerator]);
const colorScheme = theme.colors[color][5];

return (
<>
{line && <Line data={data} dataKey={dataKey} color={color} />}
<path {...rest} fill={colorScheme} fillOpacity={0.1} d={area} />
</>
);
}
export function Area<T>({
color = 'blue',
data,
dataKey,
line = true,
...rest
}: AreaProps<T>) {
const { xScale, yScale } = useD3Scales({
data,
yKey: dataKey,
});
const { theme } = useTheme();

console.log(yScale.range());

const areaGenerator = useMemo(() => {
return d3
.area<T>()
.x((_, i) => xScale(i))
.y0(yScale(0))
.y1((d) => yScale(d[dataKey]));
}, [yScale, xScale]);

const area = useMemo(() => areaGenerator(data), [areaGenerator]);
const colorScheme = theme.colors[color][5];

return (
<>
{line && <Line data={data} dataKey={dataKey} color={color} />}
<path {...rest} fill={colorScheme} fillOpacity={0.1} d={area} />
</>
);
}
N
Nesho417d ago
Result, as you can see, the height of the area is 8781, when it should be 226 (the height of the svg)
N
Nesho417d ago
The line above, using the same scales
N
Nesho417d ago
Logging the range gives me [226, 0], which is correct. Solved it. The issue was that I was doing .domain(d3.extent(data, (d) => d[yKey])) in the yScale, when I needed to give it a minimum value of 0 ,and just find the max value .domain([0, d3.max(data, (d) => d[yKey])]). The area calculates and plots correctly now.
UU
Unknown User416d ago