I am being asked to put long string values as my X axis tick labels.
I tried other charting libraries, but this one overall has worked the best for my situation. I just cannot figure out what to do with the x axis labels.
I tried to create a separate div
and map
through the values underneath the chart, but I can't maintain the alignment between the chart and the values when there are more than 7 or 8 x axis values.
I had a tickFormatter
function that cut the string at a certain number of characters/hid the overflow and was set at an angle on the x axis, but they still aren't happy with that.
This is my code currently and I feel like it is so close to being workable and I just wish that I could get the text to wrap onto more lines.
Working with SVGs is extremely confusing to me and I've tried to write functions that return SVG text elements as a custom tick, but I couldn't get it to work. Or when I pass something and it returns [object Object] as the label.
const data = React.useMemo(() => {
return orderOfItems?.map((claim, i) => ({
Item: i 1,
Claim: claim.split(" ").join("\n"),
Reach: (
incrementalReachSummary[claim]?.Summary_Metrics.Reach * 100
).toFixed(1),
}));
}, [orderOfItems, incrementalReachSummary]);
const tickFormatter = (value: string) => {
const limit = 10; // put your maximum character
if (value.length < limit) return value;
return `${value.split(" ").join("\n")}...`;
};
return (
<>
<ResponsiveContainer
align={"end"}
w={"60%"}
height={200}
aspect={2}
minWidth={"undefined"}
maxHeight={"undefined"}
>
<LineChart
data={data}
margin={{
top: 50,
right: 250,
left: 250,
bottom: 500,
}}
>
<CartesianGrid
strokeDasharray="3"
opacity={colorMode === "dark" ? 0.3 : 0.9}
/>
<XAxis
// hide={true}
dataKey={"Claim"}
interval="preserveStartEnd"
angle={-35}
tickFormatter={tickFormatter}
textAnchor={"end"}
axisLine={false}
offset={5}
tickMargin={10}
style={{
fill: colorMode === "dark" ? "#FFFFFF" : "#1A202C",
textAlign: "center",
}}
>
{/*<Label value="Claim" offset={100} position="bottom" />*/}
</XAxis>
<YAxis
type={"number"}
domain={[0, 100]}
axisLine={false}
tickLine={false}
tickCount={7}
tickMargin={10}
tickFormatter={(Reach) => `${Reach}%`}
style={{ fill: colorMode === "dark" ? "#FFFFFF" : "#1A202C" }}
/>
<Tooltip content={<CustomToolTip />} />
<Line
type="monotone"
strokeWidth={3}
dataKey="Reach"
stroke="#3182CE"
activeDot={{ r: 9 }}
>
<LabelList
dataKey="Reach"
offset={14}
position="insideTopLeft"
formatter={(Reach) => `${Reach}%`}
fill={colorMode === "dark" ? "#FFFFFF" : "#1A202C"}
/>
</Line>
</LineChart>
</ResponsiveContainer>
CodePudding user response:
You need to create a custom tick react component. Line breaks will not work. You will need to use multiple <tspan>
components with correct dy
or vertical position. Also increase the chart bottom
so lines are not hidden.
Use payload.value
to access the original value & create as many tspans
required.
<XAxis tick={<CustomizedTick />} />
Example
function CustomizedTick(props) {
const { x, y, stroke, payload } = props;
return (
<g transform={`translate(${x},${y})`}>
<text x={0} y={0} dy={16} fill="#666">
<tspan textAnchor="middle" x="0">
Line 1
</tspan>
<tspan textAnchor="middle" x="0" dy="20">
Line 2
</tspan>
<tspan textAnchor="middle" x="0" dy="40">
Line 3
</tspan>
</text>
</g>
);
}
Working codesandbox.