Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Recharts Tick Marks from Overlapping

I am developing an application which allows a user to select dynamically queried data which can then be used in Recharts visualizations. There are certain edge cases where the default formatting / rendering within recharts produces an ugly result. For example, if there are many unique values passed to the <XAxis /> component then the chart produced will likely have overlapping text for the ticks.

There does not seem to be any good "render as many ticks as possible, without overlapping" option described in the documentation. These appear to be the only options:

  1. Render all ticks (obviously leads to too many ticks)
            <XAxis
              dataKey={xAxisField.name}
              name={getXAxisLabel(xAxisField, chartType)}
              tickFormatter={
                getMetaDataType(xAxisField) ===
                "DATE"
                  ? tickEpochFormatter // force numbers to be displayed as 'YYYY-MM-DD'
                  : tickNumberFormatter
              }
              allowDataOverflow={false}
              ticks={xValues.sort()} // gets all of the values
              interval={0} // display all of values, instead of the default 5
              angle={-90} // force text to be 90, reading towards the graph
              textAnchor="end" // rather than setting "dy={50}" or something
            >
  1. Render only the start / end / start & end, which depends (seemingly) entirely on the width of the text, prior to rotation.
            <XAxis
              dataKey={xAxisField.name}
              name={getXAxisLabel(xAxisField, chartType)}
              tickFormatter={
                getMetaDataType(xAxisField) ===
                "DATE"
                  ? tickEpochFormatter // force numbers to be displayed as 'YYYY-MM-DD'
                  : tickNumberFormatter
              }
              allowDataOverflow={false}
              ticks={xValues.sort()} // gets all of the values
              interval="preserveStart" // ensure that everything can be read, giving preference to the "left"???
              angle={-90} // force text to be 90, reading towards the graph
              textAnchor="end" // rather than setting "dy={50}" or something
            >
  1. Hardcode the number of intervals to ensure a maximum? I'm not sure if this is a viable option since I would need to know how many ticks are truly overlapping. Just seems like a crude approach.

Is it even possible to have Recharts render as many things as possible, even if they are rotated 90 degrees, and then selectively choose what has enough space to display? Is it possible to have the angle property dynamically update based on the length of the tick mark texts?

Here is a list of links, none of which seems to answer these questions:

Recharts Docs

  • Recharts XAxis Docs
  • Recharts LineChartAxisInterval Docs

Github Recharts repo

  • Show all ticks
  • Vertical Axis Label
  • Rotated Axis Labels
  • Rotate tick text
  • Axis Labels Display Over Data
  • Axis Labels Look Awful
  • Last XAxis label not aligned with tick mark when rotated -45 degrees
  • Prevent hiding of tick labels
  • Missing ticks on x-axis
  • Long strings in labels generate overlap in YAxis for horizontal barchart

StackOverflow Posts

  • Scalable YAxis Label
  • Display all XAxis ticks
  • YAxis Ticks don't auto calculate
  • Set Label Margin

Here's a picture of the problematic rendering I want to clean up:

All ticks rendered and overlapping

Also, please note that normally I would prefer to stick to the same library that I have been using, but if another library is better suited for this use-case, I would like to consider switching!

like image 940
Torc Avatar asked Jul 08 '20 20:07

Torc


2 Answers

I had the same problem, ended up removing the interval property which set the ticks to be sort-of-dynamic but had only 4 or 5 ticks.

So I set the minTickGap to some negative value. the result was that more ticks appeared on the axis

 <XAxis dataKey="date"
        angle={45}
        dx={15}
        dy={20}
        minTickGap={-200}
        axisLine={false}/>

before before

after: after

like image 176
Ivan Yulin Avatar answered Oct 15 '22 20:10

Ivan Yulin


I had the same problem, ended up removing the interval property which set the ticks to be sort-of-dynamic but had only 4 or 5 ticks.

So I set the minTickGap to some negative value. the result was that more ticks appeared on the axis

 <XAxis dataKey="date"
        angle={45}
        dx={15}
        dy={20}
        minTickGap={-200}
        axisLine={false}/>

before before

after: after

like image 1
Ivan Yulin Avatar answered Nov 02 '22 09:11

Ivan Yulin