mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.53k stars 1.32k forks source link

[docs] Document how the component order impact the overlapping #10350

Closed wascou closed 8 months ago

wascou commented 1 year ago

Duplicates

Latest version

Summary πŸ’‘

As a developper, when adding SVG components in a ScatterChart, I'm expecting to have the data points "on top" of all the other SVG components inserted. In re:Charts, there's a feature called always on top that allow to svg elements in the drawing zone, such as reference lines, reference areas or whatever and also specify that data points are always on top of the plot.

It's important for background elements that overlaps data points and prevent classic beavoir for highlight and tooltip.

Examples 🌈

<ScatterChart
      height={500}
      margin={{ top: 18, right: 40, left: 70, bottom: 40 }}
      series={[
        {
          data: serie.map((v: any) => ({
            x: v.x,
            y: v.y,
            id: v.id
          }))
        }
      ]}
    >
      <GreenPolygon />
    </ScatterChart>

and GreenPolygon component:

export const GreenPolygon = () => {
  let { left, top, width, height } = useDrawingArea()
  return (
    <polygon
      points={`${left},${top} ${left},${top + height} ${left + width},${top}`}
      fill="green"
      fillOpacity={0.05}
      strokeWidth={0}
    />
  )
}

Motivation πŸ”¦

For example, in this scatter chart, the serie is drawn and then other areas are drown later to provide some graphical help.

As mentioned in the SVG RFC, order is defined by order of apparition on the Svg and thus in the code. In this scenario, items are not clickable and don't trigger tooltip or highlight feature.

image

I found a solution after several tries and basically select all the SVG G nodes which have no classes (ie not the axis) and I put them at the end so they are drawn on top of all others.

 const elements = document.querySelectorAll("svg > g:not([class])")
    for (const element of elements) {
      const parent = element.parentNode
      parent?.appendChild(parent?.removeChild(element))
    }

This is just a work around until you provide exactly the same feature in the ScatterChart component.

Order ID πŸ’³ (optional)

No response

alexfauquette commented 1 year ago

When starting to add custom elements, it might be easier to use composition.

I think <ScatterChart><CustomElement/></ScatterChart> is once f you need to add definitions into the SVG. Thing for which the order does not matter such as

For custom elements, this might be more appropriate

<ChartContainer
  width={600}
  height={300}
  series={[
    {
      type: "scatter",
      label: "series A",
      data: data.map((v) => ({ x: v.x1, y: v.y1, id: v.id }))
    }
  ]}
>
  <GreenPolygon />
  <ChartsXAxis axisId={DEFAULT_X_AXIS_KEY} />
  <ChartsYAxis axisId={DEFAULT_Y_AXIS_KEY} />
  <ScatterPlot />
</ChartContainer>

What do you think about this solution?

wascou commented 1 year ago

hey @alexfauquette

Thanks for that. I'm still struggling doing what I want.

I'm blocked on:

Many thanks. --W

alexfauquette commented 1 year ago

Where should I put valueFormatter for an axis ? It is not taken in account in the ScatterPlot.xAxis Tooltip should go on ScatterPlot, right? It is not taken in account in the xAxis too

No sure to understand the issue. Here is the most advanced demo with tooltip on scatter chart https://mui.com/x/react-charts/scatter-demo/#multipleyaxesscatterchart

I even customized it a bit more to format the x axis (adding "cm") the y axis (adding "kg" and "lb") and the tooltip such that y value mach axes for each series.

https://codesandbox.io/s/dazzling-sanne-c34zrz?file=/Demo.tsx

But I agree formating should be properly documented

How do you ses a "fullwidth" on ChartContainer ? On ScatterChart, if you don't give a width, it applies a 100% width automatically which is what I want. Without it, ContainerChart is raising an error ("I need a width")

You should use <ResponsiveChartContainer />. We need a dedicated docs page for the composition

wascou commented 1 year ago

Hi Alex,

Thanks for the width, I used the responsive component, works like a charm.

Splitting the ScatterChart in ResponsiveChartContainer and ScatterPlot comes with other challenge as props has to be reassigned to one component or the other.

My code looks now like this:

<ResponsiveChartContainer
      height={500}
      series={[
        {
          data: serie.map((v: any) => ({
            x: v.x,
            y: v.y,
            id: v.id
          })),
          label: "Label",
          type: "scatter"
        }
      ]}
    >
      <ChartsXAxis axisId={DEFAULT_X_AXIS_KEY} label="X" />
      <ChartsYAxis axisId={DEFAULT_Y_AXIS_KEY} label="Y" />
      <ScatterPlot
        tooltip={{
          trigger: "item",
          itemContent: CustomItemTooltipContent
        }}
        yAxis={[
          {
            valueFormatter: tickFormatter
          }
        ]}
        xAxis={[
          {
            valueFormatter: tickFormatter
          }
        ]}
      />
    </ResponsiveChartContainer>

The tickformatter function is never called neither the tooltip. Any suggestions?

wascou commented 1 year ago

Ok, I understood the point about composition, so for tooltip, I have: <ChartsTooltip trigger="item" itemContent={CustomItemTooltipContent} />

wascou commented 1 year ago

OK,I found it.

For any reasons, VScode is not autocompleting. Every xAxis element from the ScatterChart can be set in the ChartXAxis component.

 <ChartsXAxis
        axisId={DEFAULT_X_AXIS_KEY}
        label="Label"
        min={0}
        max={100}
        valueFormatter={tickFormatter}
      />
alexfauquette commented 1 year ago

I just reopening the issue to track your question. I will close it back when all those answers will be in the docs

github-actions[bot] commented 8 months ago

:warning: This issue has been closed. If you have a similar problem, please open a new issue and provide details about your specific problem. If you can provide additional information related to this topic that could help future readers, please feel free to leave a comment.

How did we do @wascou? Your experience with our support team matters to us. If you have a moment, please share your thoughts through our brief survey.