Skip to content

Commit

Permalink
[charts] Filter item outside the drawing area for perf (#14281)
Browse files Browse the repository at this point in the history
Co-authored-by: Jose Quintas <[email protected]>
  • Loading branch information
alexfauquette and JCQuintas authored Nov 11, 2024
1 parent c14c5ab commit dc87d16
Show file tree
Hide file tree
Showing 11 changed files with 539 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';
import * as React from 'react';
import PropTypes from 'prop-types';
import type {} from '../typeOverloads';
import { Watermark } from '@mui/x-license/Watermark';
import { ChartContainerProps } from '@mui/x-charts/ChartContainer';
import { ResizableContainer } from '@mui/x-charts/internals';
Expand Down
112 changes: 67 additions & 45 deletions packages/x-charts/src/BarChart/BarPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { BarElement, BarElementSlotProps, BarElementSlots } from './BarElement';
import { AxisDefaultized } from '../models/axis';
import { BarItemIdentifier } from '../models';
import getColor from './getColor';
import { useChartId } from '../hooks';
import { useChartId, useDrawingArea } from '../hooks';
import { AnimationData, CompletedBarData, MaskData } from './types';
import { BarClipPath } from './BarClipPath';
import { BarLabelItemProps, BarLabelSlotProps, BarLabelSlots } from './BarLabel/BarLabelItem';
Expand Down Expand Up @@ -92,6 +92,7 @@ const useAggregatedData = (): {
useBarSeries() ??
({ series: {}, stackingGroups: [], seriesOrder: [] } as SeriesFormatterResult<'bar'>);
const axisData = useCartesianContext();
const drawingArea = useDrawingArea();
const chartId = useChartId();

const { series, stackingGroups } = seriesData;
Expand All @@ -102,6 +103,12 @@ const useAggregatedData = (): {
const masks: Record<string, MaskData> = {};

const data = stackingGroups.flatMap(({ ids: groupIds }, groupIndex) => {
const xMin = drawingArea.left;
const xMax = drawingArea.left + drawingArea.width;

const yMin = drawingArea.top;
const yMax = drawingArea.top + drawingArea.height;

return groupIds.flatMap((seriesId) => {
const xAxisId = series[seriesId].xAxisId ?? defaultXAxisId;
const yAxisId = series[seriesId].yAxisId ?? defaultYAxisId;
Expand Down Expand Up @@ -132,54 +139,69 @@ const useAggregatedData = (): {

const { stackedData } = series[seriesId];

return stackedData.map((values, dataIndex: number) => {
const valueCoordinates = values.map((v) => (verticalLayout ? yScale(v)! : xScale(v)!));

const minValueCoord = Math.round(Math.min(...valueCoordinates));
const maxValueCoord = Math.round(Math.max(...valueCoordinates));

const stackId = series[seriesId].stack;

const result = {
seriesId,
dataIndex,
layout: series[seriesId].layout,
x: verticalLayout ? xScale(xAxis[xAxisId].data?.[dataIndex])! + barOffset : minValueCoord,
y: verticalLayout ? minValueCoord : yScale(yAxis[yAxisId].data?.[dataIndex])! + barOffset,
xOrigin: xScale(0)!,
yOrigin: yScale(0)!,
height: verticalLayout ? maxValueCoord - minValueCoord : barWidth,
width: verticalLayout ? barWidth : maxValueCoord - minValueCoord,
color: colorGetter(dataIndex),
value: series[seriesId].data[dataIndex],
maskId: `${chartId}_${stackId || seriesId}_${groupIndex}_${dataIndex}`,
};

if (!masks[result.maskId]) {
masks[result.maskId] = {
id: result.maskId,
width: 0,
height: 0,
hasNegative: false,
hasPositive: false,
layout: result.layout,
return stackedData
.map((values, dataIndex: number) => {
const valueCoordinates = values.map((v) => (verticalLayout ? yScale(v)! : xScale(v)!));

const minValueCoord = Math.round(Math.min(...valueCoordinates));
const maxValueCoord = Math.round(Math.max(...valueCoordinates));

const stackId = series[seriesId].stack;

const result = {
seriesId,
dataIndex,
layout: series[seriesId].layout,
x: verticalLayout
? xScale(xAxis[xAxisId].data?.[dataIndex])! + barOffset
: minValueCoord,
y: verticalLayout
? minValueCoord
: yScale(yAxis[yAxisId].data?.[dataIndex])! + barOffset,
xOrigin: xScale(0)!,
yOrigin: yScale(0)!,
x: 0,
y: 0,
height: verticalLayout ? maxValueCoord - minValueCoord : barWidth,
width: verticalLayout ? barWidth : maxValueCoord - minValueCoord,
color: colorGetter(dataIndex),
value: series[seriesId].data[dataIndex],
maskId: `${chartId}_${stackId || seriesId}_${groupIndex}_${dataIndex}`,
};
}

const mask = masks[result.maskId];
mask.width = result.layout === 'vertical' ? result.width : mask.width + result.width;
mask.height = result.layout === 'vertical' ? mask.height + result.height : result.height;
mask.x = Math.min(mask.x === 0 ? Infinity : mask.x, result.x);
mask.y = Math.min(mask.y === 0 ? Infinity : mask.y, result.y);
mask.hasNegative = mask.hasNegative || (result.value ?? 0) < 0;
mask.hasPositive = mask.hasPositive || (result.value ?? 0) > 0;

return result;
});
if (
result.x > xMax ||
result.x + result.width < xMin ||
result.y > yMax ||
result.y + result.height < yMin
) {
return null;
}

if (!masks[result.maskId]) {
masks[result.maskId] = {
id: result.maskId,
width: 0,
height: 0,
hasNegative: false,
hasPositive: false,
layout: result.layout,
xOrigin: xScale(0)!,
yOrigin: yScale(0)!,
x: 0,
y: 0,
};
}

const mask = masks[result.maskId];
mask.width = result.layout === 'vertical' ? result.width : mask.width + result.width;
mask.height = result.layout === 'vertical' ? mask.height + result.height : result.height;
mask.x = Math.min(mask.x === 0 ? Infinity : mask.x, result.x);
mask.y = Math.min(mask.y === 0 ? Infinity : mask.y, result.y);
mask.hasNegative = mask.hasNegative || (result.value ?? 0) < 0;
mask.hasPositive = mask.hasPositive || (result.value ?? 0) > 0;

return result;
})
.filter((rectangle) => rectangle !== null);
});
});

Expand Down
Loading

0 comments on commit dc87d16

Please sign in to comment.