rusackas commented on code in PR #42247:
URL: https://github.com/apache/superset/pull/42247#discussion_r3618175855
##########
superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx:
##########
@@ -63,10 +69,97 @@ export default function EchartsTimeseries({
onLegendScroll,
}: TimeseriesChartTransformedProps) {
const { stack } = formData;
+ const theme = useTheme();
const echartRef = useRef<EchartsHandler | null>(null);
// eslint-disable-next-line no-param-reassign
refs.echartRef = echartRef;
const clickTimer = useRef<ReturnType<typeof setTimeout>>();
+
+ // Draggable percent-change baseline: when the rebase view is active, a
+ // vertical line is drawn on the plot; dragging it re-indexes every series
+ // to the hovered point via the composable rebase, entirely client-side.
+ const rebaseEnabled = Boolean(
+ (formData as { rebasePercentChange?: boolean }).rebasePercentChange,
+ );
+ useEffect(() => {
+ if (!rebaseEnabled) return undefined;
+ const chart = echartRef.current?.getEchartInstance?.();
+ if (!chart) return undefined;
+
+ const option = chart.getOption() as {
+ series?: { data?: SeriesDataPoint[] }[];
+ };
+ const baseSeries = (option.series ?? []).map(s =>
+ Array.isArray(s.data) ? (s.data as SeriesDataPoint[]) : [],
+ );
+ const xs = Array.from(
+ new Set(baseSeries.flat().map(([x]) => Number(x))),
+ ).sort((a, b) => a - b);
+ if (xs.length === 0) return undefined;
+ let baselineX = xs[0];
+
+ const applyBaseline = (newX: number) => {
+ baselineX = newX;
+ chart.setOption({
+ series: baseSeries.map(data => ({
+ data: rebaseSeriesData(data, newX),
+ })),
+ });
+ };
+
+ const drawHandle = () => {
+ const gridRect = { top: 0, height: chart.getHeight() };
+ let px: number;
+ try {
+ [px] = [chart.convertToPixel({ xAxisIndex: 0 }, baselineX) as number];
+ } catch {
+ return;
+ }
+ chart.setOption({
+ graphic: [
+ {
+ id: 'percent-change-baseline',
+ type: 'rect',
+ x: px - 4,
+ y: gridRect.top,
+ shape: { width: 8, height: gridRect.height },
+ style: { fill: theme.colorFillQuaternary },
+ cursor: 'ew-resize',
+ draggable: true,
+ z: 100,
+ ondrag(this: { x: number; y: number }) {
+ this.y = gridRect.top;
+ const dataX = chart.convertFromPixel(
+ { xAxisIndex: 0 },
+ this.x + 4,
+ ) as number;
+ const snapped = snapToNearestX(xs, dataX);
+ if (snapped !== undefined && snapped !== baselineX) {
+ applyBaseline(snapped);
+ }
Review Comment:
Fixed — ondrag now coalesces to at most one setOption per animation frame
instead of rebasing every series on every raw pointer-move event.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]