FormidableLabs / victory

A collection of composable React components for building interactive data visualizations
http://commerce.nearform.com/open-source/victory/
Other
10.85k stars 525 forks source link

Avoiding crowding of labels in VictoryLine chart #2665

Open BhargaviAnnadevara opened 8 months ago

BhargaviAnnadevara commented 8 months ago

Describe the bug When a large dataset is plotted as a line chart, noticing that the tick labels for the data on the chart are overlapping with each other causing it to become obscure. Is there a way to avoid this issue? Can the library decide which labels to display without overlapping? Or, can we provide a set of labels to be displayed, like tickValues maybe?

Victory version Which npm version are you using? N/A

Code This issue can be reproduced in the editable source present in VictoryLine chart with the below snippet:

<VictoryChart
  theme={VictoryTheme.material}
>
  <VictoryLine
    style={{
      data: { stroke: "#c43a31" },
      parent: { border: "1px solid #ccc"}
    }}
    data={[
{
        x: new Date(2023, 6, 1),
        y: 0
    },
    {
        x: new Date(2023, 7, 31),
        y: 17.97
    },
    {
        x: new Date(2023, 8, 1),
        y: 20.55
    },
    {
        x: new Date(2023, 8, 2),
        y: 28.27
    },
    {
        x: new Date(2023, 8, 3),
        y: 9.78
    },
    {
        x: new Date(2023, 8, 4),
        y: 0
    },
    {
        x: new Date(2023, 8, 5),
        y: 9.48
    },
    {
        x: new Date(2023, 8, 6),
        y: 11.38
    },
    {
        x: new Date(2023, 8, 7),
        y: 6.95
    },
    {
        x: new Date(2023, 8, 8),
        y: 21.64
    },
    {
        x: new Date(2023, 8, 9),
        y: 22.3
    },
    {
        x: new Date(2023, 8, 10),
        y: 24.42
    },
    {
        x: new Date(2023, 8, 11),
        y: 6.59
    },
    {
        x: new Date(2023, 8, 12),
        y: 17.09
    },
    {
        x: new Date(2023, 8, 13),
        y: 0
    },
    {
        x: new Date(2023, 8, 14),
        y: 0
    },
    {
        x: new Date(2023, 8, 15),
        y: 7.41
    },
    {
        x: new Date(2023, 8, 16),
        y: 17.5
    },
    {
        x: new Date(2023, 8, 17),
        y: 15.97
    }, {
        x: new Date(2023, 8, 18),
        y: 0.91
    },
    {
        x: new Date(2023, 8, 19),
        y: 8.75
    },
    {
        x: new Date(2023, 8, 20),
        y: 7.39
    },
    {
        x: new Date(2023, 8, 21),
        y: 10.43
    },
    {
        x: new Date(2023, 8, 22),
        y: 16.81
    },
    {
        x: new Date(2023, 8, 23),
        y: 9.26
    },
    {
        x: new Date(2023, 8, 24),
        y: 12.98
    },
    {
        x: new Date(2023, 8, 25),
        y: 0
    },
    {
        x: new Date(2023, 8, 26),
        y: 0
    },
    {
        x: new Date(2023, 8, 27),
        y: 9.26
    },
    {
        x: new Date(2023, 8, 28),
        y: 22.25
    },
    {
        x: new Date(2023, 8, 29),
        y: 19.02
    },
    {
        x: new Date(2023, 8, 30),
        y: 23.65
    },
    {
        x: new Date(2023, 9, 6),
        y: 62.25
    }
    ]}
    labels={({ datum }) => `${datum.y}k`}
  />
</VictoryChart>

Expected behavior Victory should automatically and selectively render a limited set of labels that helps render the chart neatly, or, should accept it as a prop similar to tickValues.

Screenshots image

Additional context Another observation from this example is that some labels like 0k are overlapping with the y-axis line, which shouldn't happen. Although the position of the labels can be adjusted manually, I feel this should be taken care of automatically by the library. image

Any inputs are appreciated!

chriszrc commented 1 month ago

Is there any approach we can use in the interim? And really this can affect many of the charts, from box plots to scatter charts-

carbonrobot commented 1 month ago

I can't think of any easy way for Victory to determine which labels to display. A naive implementation that measures for overlap would bias to the first set of labels and end up skipping labels at uneven intervals.

I think we need to see a mockup of what a solution would look like, along with a set of rules for determining the display logic. Or if there is another charting library that offers a similar implementation we can explore how they do it.

chriszrc commented 1 month ago

As a start, I think just support for a user supplied naive thinning function (maybe which perhaps could also receive the zoom level so thinning could be turned down or off as well) would at least be something. True overlap detection would take more work 😞