Skip to content

Commit

Permalink
fix(D3 plugin): fix AxisX render performance (#285)
Browse files Browse the repository at this point in the history
  • Loading branch information
kuzmadom authored Sep 11, 2023
1 parent 2f52c61 commit 0f31885
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 37 deletions.
37 changes: 15 additions & 22 deletions src/plugins/d3/renderer/components/AxisX.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import {axisBottom, select} from 'd3';
import type {AxisScale, AxisDomain, Selection} from 'd3';
import type {AxisScale, AxisDomain} from 'd3';

import {block} from '../../../../utils/cn';

Expand All @@ -17,26 +17,6 @@ type Props = {
scale: ChartScale;
};

// Note: this method do not prepared for rotated labels
const removeOverlappingXTicks = (axis: Selection<SVGGElement, unknown, null, undefined>) => {
const a = axis.selectAll('g.tick').nodes();

if (a.length <= 1) {
return;
}

for (let i = 0, x = 0; i < a.length; i++) {
const node = a[i] as Element;
const r = node.getBoundingClientRect();

if (r.left < x) {
node?.parentNode?.removeChild(node);
} else {
x = r.right + EMPTY_SPACE_BETWEEN_LABELS;
}
}
};

// FIXME: add overflow ellipsis for the labels that out of boundaries
export const AxisX = ({axis, width, height, scale}: Props) => {
const ref = React.useRef<SVGGElement>(null);
Expand Down Expand Up @@ -102,7 +82,20 @@ export const AxisX = ({axis, width, height, scale}: Props) => {
.text(axis.title.text);
}

removeOverlappingXTicks(svgElement);
let elementX = 0;
svgElement
.selectAll('.tick')
.filter(function () {
const node = this as unknown as Element;
const r = node.getBoundingClientRect();

if (r.left < elementX) {
return true;
}
elementX = r.right + EMPTY_SPACE_BETWEEN_LABELS;
return false;
})
.remove();
}, [axis, width, height, scale]);

return <g ref={ref} />;
Expand Down
19 changes: 9 additions & 10 deletions src/plugins/d3/renderer/hooks/useAxisScales/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,16 @@ const filterCategoriesByVisibleSeries = (args: {
}) => {
const {axisDirection, categories, series} = args;

return categories.filter((category) => {
return series.some((s) => {
return (
isSeriesWithCategoryValues(s) &&
s.data.some((d) => {
const dataCategory = getDataCategoryValue({axisDirection, categories, data: d});
return dataCategory === category;
})
);
});
const visibleCategories = new Set();
series.forEach((s) => {
if (isSeriesWithCategoryValues(s)) {
s.data.forEach((d) => {
visibleCategories.add(getDataCategoryValue({axisDirection, categories, data: d}));
});
}
});

return categories.filter((c) => visibleCategories.has(c));
};

const createScales = (args: Args) => {
Expand Down
11 changes: 6 additions & 5 deletions src/plugins/d3/renderer/hooks/useShapes/scatter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,19 @@ export function ScatterSeriesShape(props: ScatterSeriesShapeProps) {
}

const svgElement = select(ref.current);
svgElement.selectAll('*').remove();
const preparedData =
xAxis.type === 'category' || yAxis[0]?.type === 'category'
? series.data
: prepareLinearScatterData(series.data);

svgElement
.selectAll('allPoints')
.selectAll('circle')
.data(preparedData)
.enter()
.append('circle')
.attr('class', b('point'))
.join(
(enter) => enter.append('circle').attr('class', b('point')),
(update) => update,
(exit) => exit.remove(),
)
.attr('fill', (d) => d.color || series.color || '')
.attr('r', (d) => d.radius || DEFAULT_SCATTER_POINT_RADIUS)
.attr('cx', (d) => getCxAttr({point: d, xAxis, xScale}))
Expand Down

0 comments on commit 0f31885

Please sign in to comment.