Skip to content

Commit

Permalink
[charts] Limit the trigger of exit charts (mui#13682)
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Fauquette <[email protected]>
Co-authored-by: Jose C Quintas Jr <[email protected]>
  • Loading branch information
2 people authored and DungTiger committed Jul 23, 2024
1 parent b5ae667 commit bcda197
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 16 deletions.
5 changes: 4 additions & 1 deletion packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ const LineChartPro = React.forwardRef(function LineChartPro(props: LineChartProP
<ChartsAxisHighlight {...axisHighlightProps} />
</g>
<ChartsAxis {...chartsAxisProps} />
<MarkPlotZoom {...markPlotProps} />
<g data-drawing-container>
{/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */}
<MarkPlotZoom {...markPlotProps} />
</g>
<LineHighlightPlot {...lineHighlightPlotProps} />
<ChartsLegend {...legendProps} />
{!props.loading && <ChartsTooltip {...tooltipProps} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro(
{!props.disableVoronoi && <ChartsVoronoiHandler {...voronoiHandlerProps} />}
<ChartsAxis {...chartsAxisProps} />
{props.grid && <ChartsGrid {...gridProps} />}
<ScatterPlot {...scatterPlotProps} />
<g data-drawing-container>
{/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */}
<ScatterPlot {...scatterPlotProps} />
</g>
<ChartsOverlay {...overlayProps} />
<ChartsLegend {...legendProps} />
<ChartsAxisHighlight {...axisHighlightProps} />
Expand Down
5 changes: 4 additions & 1 deletion packages/x-charts/src/LineChart/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,10 @@ const LineChart = React.forwardRef(function LineChart(props: LineChartProps, ref
<ChartsAxisHighlight {...axisHighlightProps} />
</g>
<ChartsAxis {...chartsAxisProps} />
<MarkPlot {...markPlotProps} />
<g data-drawing-container>
{/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */}
<MarkPlot {...markPlotProps} />
</g>
<LineHighlightPlot {...lineHighlightPlotProps} />
<ChartsLegend {...legendProps} />
{!props.loading && <ChartsTooltip {...tooltipProps} />}
Expand Down
5 changes: 4 additions & 1 deletion packages/x-charts/src/ScatterChart/ScatterChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ const ScatterChart = React.forwardRef(function ScatterChart(props: ScatterChartP
{!props.disableVoronoi && <ChartsVoronoiHandler {...voronoiHandlerProps} />}
<ChartsAxis {...chartsAxisProps} />
{props.grid && <ChartsGrid {...gridProps} />}
<ScatterPlot {...scatterPlotProps} />
<g data-drawing-container>
{/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */}
<ScatterPlot {...scatterPlotProps} />
</g>
<ChartsOverlay {...overlayProps} />
<ChartsLegend {...legendProps} />
<ChartsAxisHighlight {...axisHighlightProps} />
Expand Down
20 changes: 14 additions & 6 deletions packages/x-charts/src/context/DrawingProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ export type DrawingArea = {
* @param {Object} point The point to check.
* @param {number} point.x The x coordinate of the point.
* @param {number} point.y The y coordinate of the point.
* @param {Element} targetElement The target element if relevant.
* @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise.
*/
isPointInside: (point: { x: number; y: number }) => boolean;
isPointInside: (point: { x: number; y: number }, targetElement?: Element) => boolean;
};

export const DrawingContext = React.createContext<
Expand Down Expand Up @@ -86,11 +87,18 @@ export function DrawingProvider(props: DrawingProviderProps) {
const chartId = useId();

const isPointInside = React.useCallback<DrawingArea['isPointInside']>(
({ x, y }) =>
x >= drawingArea.left &&
x <= drawingArea.left + drawingArea.width &&
y >= drawingArea.top &&
y <= drawingArea.top + drawingArea.height,
({ x, y }, targetElement) => {
// For element allowed to overflow, wrapping them in <g data-drawing-container /> make them fully part of the drawing area.
if (targetElement && targetElement.closest('[data-drawing-container]')) {
return true;
}
return (
x >= drawingArea.left &&
x <= drawingArea.left + drawingArea.width &&
y >= drawingArea.top &&
y <= drawingArea.top + drawingArea.height
);
},
[drawingArea],
);

Expand Down
16 changes: 10 additions & 6 deletions packages/x-charts/src/hooks/useAxisEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => {

// Use a ref to avoid rerendering on every mousemove event.
const mousePosition = React.useRef({
isInChart: false,
x: -1,
y: -1,
});
Expand Down Expand Up @@ -94,6 +95,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => {

const handleOut = () => {
mousePosition.current = {
isInChart: false,
x: -1,
y: -1,
};
Expand All @@ -104,15 +106,17 @@ export const useAxisEvents = (disableAxisListener: boolean) => {
const target = 'targetTouches' in event ? event.targetTouches[0] : event;
const svgPoint = getSVGPoint(element, target);

mousePosition.current = {
x: svgPoint.x,
y: svgPoint.y,
};
mousePosition.current.x = svgPoint.x;
mousePosition.current.y = svgPoint.y;

if (!drawingArea.isPointInside(svgPoint)) {
dispatch({ type: 'exitChart' });
if (!drawingArea.isPointInside(svgPoint, event.target as SVGElement)) {
if (mousePosition.current.isInChart) {
dispatch({ type: 'exitChart' });
mousePosition.current.isInChart = false;
}
return;
}
mousePosition.current.isInChart = true;
const newStateX = getNewAxisState(xAxis[usedXAxis], svgPoint.x);
const newStateY = getNewAxisState(yAxis[usedYAxis], svgPoint.y);

Expand Down

0 comments on commit bcda197

Please sign in to comment.