Skip to content

Commit 79bcd08

Browse files
authored
Merge pull request #4624 from VisActor/fix/restore-axis-grid-after-update
fix: restore axis grid after visibility update
2 parents 94ea07c + e922211 commit 79bcd08

3 files changed

Lines changed: 119 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "fix: restore existing axis grid graphics when grid visibility is enabled again through updateSpec with animation disabled",
5+
"type": "patch",
6+
"packageName": "@visactor/vchart"
7+
}
8+
],
9+
"packageName": "@visactor/vchart",
10+
"email": "lixuef1313@163.com"
11+
}

packages/vchart/__tests__/unit/core/update-effects.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type TestChartModel = {
4040
getComponentsByKey: (key: string) => Array<{
4141
position?: string;
4242
getOrient?: () => string;
43+
getVRenderComponents?: () => TestVRenderGraphic[];
4344
getScale?: () => { domain: () => unknown[] };
4445
getTickData?: () => {
4546
getDataView: () => {
@@ -52,6 +53,15 @@ type TestChartModel = {
5253
reDataFlow: () => void;
5354
};
5455

56+
type TestVRenderGraphic = {
57+
name?: string;
58+
attribute?: {
59+
visible?: boolean;
60+
visibleAll?: boolean;
61+
};
62+
forEachChildren?: (cb: (child: TestVRenderGraphic) => void) => void;
63+
};
64+
5565
const getChartModel = (chart: VChart) => chart.getChart() as unknown as TestChartModel;
5666

5767
const spyOnDataStages = (chart: VChart) => {
@@ -261,6 +271,29 @@ const createAxisElementVisibleSpec = (element: AxisVisibleElement, visible: bool
261271
]
262272
});
263273

274+
const createLineAxisGridVisibleSpec = (gridVisible: boolean, animation: boolean): ILineChartSpec =>
275+
({
276+
type: 'line',
277+
animation,
278+
data: [
279+
{
280+
id: 'data',
281+
values: [
282+
{ x: 'A', y: 11 },
283+
{ x: 'B', y: 12 },
284+
{ x: 'C', y: 23 },
285+
{ x: 'D', y: 14 }
286+
]
287+
}
288+
],
289+
xField: 'x',
290+
yField: 'y',
291+
axes: [
292+
{ orient: 'left', grid: { visible: gridVisible } },
293+
{ orient: 'bottom', grid: { visible: gridVisible } }
294+
]
295+
} as ILineChartSpec);
296+
264297
const createLegendAppearanceSpec = (
265298
labelFill: string,
266299
position: 'start' | 'middle' | 'end' = 'middle',
@@ -1282,6 +1315,55 @@ const getAxisTickTransformOptions = (chart: VChart, orient: 'angle' | 'radius')
12821315
return tickTransform?.options as { startAngle?: number };
12831316
};
12841317

1318+
const findAxisGridComponent = (chart: VChart, orient: 'left' | 'bottom') => {
1319+
const axis = getChartModel(chart)
1320+
.getComponentsByKey('axes')
1321+
.find(axisItem => axisItem.getOrient?.() === orient);
1322+
1323+
return axis?.getVRenderComponents?.()[1];
1324+
};
1325+
1326+
const getAxisGridComponent = (chart: VChart, orient: 'left' | 'bottom') => {
1327+
const gridComponent = findAxisGridComponent(chart, orient);
1328+
expect(gridComponent).toBeDefined();
1329+
1330+
return gridComponent as TestVRenderGraphic;
1331+
};
1332+
1333+
const collectGraphicsByName = (graphic: TestVRenderGraphic, name: string) => {
1334+
const graphics: TestVRenderGraphic[] = [];
1335+
const visit = (current: TestVRenderGraphic) => {
1336+
if (current.name === name) {
1337+
graphics.push(current);
1338+
}
1339+
current.forEachChildren?.(visit);
1340+
};
1341+
1342+
visit(graphic);
1343+
return graphics;
1344+
};
1345+
1346+
const expectAxisGridLinesShown = (chart: VChart, orient: 'left' | 'bottom') => {
1347+
const gridComponent = getAxisGridComponent(chart, orient);
1348+
const gridLines = collectGraphicsByName(gridComponent, 'axis-grid-line');
1349+
1350+
expect(gridComponent.attribute?.visibleAll).not.toBe(false);
1351+
expect(gridLines.length).toBeGreaterThan(0);
1352+
gridLines.forEach(gridLine => {
1353+
expect(gridLine.attribute?.visible).not.toBe(false);
1354+
});
1355+
};
1356+
1357+
const expectAxisGridHidden = (chart: VChart, orient: 'left' | 'bottom') => {
1358+
const gridComponent = findAxisGridComponent(chart, orient);
1359+
1360+
if (!gridComponent) {
1361+
return;
1362+
}
1363+
1364+
expect(gridComponent.attribute?.visibleAll).toBe(false);
1365+
};
1366+
12851367
const getFirstScatterGraphic = (chart: VChart) => {
12861368
const scatterSeries = chart
12871369
.getChart()
@@ -2196,6 +2278,29 @@ describe('vchart scoped update effects', () => {
21962278
}
21972279
});
21982280

2281+
it('restores existing axis grid lines after animation false hides and shows them', async () => {
2282+
const chart = new VChart(createLineAxisGridVisibleSpec(true, true), { dom });
2283+
2284+
try {
2285+
chart.renderSync();
2286+
2287+
expectAxisGridLinesShown(chart, 'left');
2288+
expectAxisGridLinesShown(chart, 'bottom');
2289+
2290+
await chart.updateSpec(createLineAxisGridVisibleSpec(false, false));
2291+
2292+
expectAxisGridHidden(chart, 'left');
2293+
expectAxisGridHidden(chart, 'bottom');
2294+
2295+
await chart.updateSpec(createLineAxisGridVisibleSpec(true, false));
2296+
2297+
expectAxisGridLinesShown(chart, 'left');
2298+
expectAxisGridLinesShown(chart, 'bottom');
2299+
} finally {
2300+
chart.release();
2301+
}
2302+
});
2303+
21992304
it('keeps axis min max updates on the series data path', () => {
22002305
const chart = new VChart(createAxisAppearanceSpec(), { dom, animation: false });
22012306

packages/vchart/src/mark/component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ export class ComponentMark extends BaseMark<ICommonSpec> implements IComponentMa
190190
this._component && this._product.appendChild(this._component);
191191
} else {
192192
this._component.setAttributes(attrs as any);
193+
if (this._product && this._component.parent !== this._product) {
194+
this._product.appendChild(this._component);
195+
}
193196
}
194197

195198
if (this._component) {

0 commit comments

Comments
 (0)