Nesho
Nesho2y ago

✅ – 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 };
}
6 Replies
Nesho
NeshoOP2y 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} />
</>
);
}
Nesho
NeshoOP2y ago
Result, as you can see, the height of the area is 8781, when it should be 226 (the height of the svg)
Nesho
NeshoOP2y ago
The line above, using the same scales
Nesho
NeshoOP2y 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.
reactibot
reactibot2y ago
This question has an answer! Thank you for helping 😄 If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1078990067244216330
reactibot
reactibot2y ago
This thread hasn’t had any activity in 12 hours, so it’s now locked. Threads are closed automatically after 12 hours. If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1078990067244216330