diff --git a/__tests__/integration/api-chart-auto-fit.spec.ts b/__tests__/integration/api-chart-auto-fit.spec.ts index 66d9f45b99..1cb417af25 100644 --- a/__tests__/integration/api-chart-auto-fit.spec.ts +++ b/__tests__/integration/api-chart-auto-fit.spec.ts @@ -9,6 +9,7 @@ describe('chart.options.autoFit', () => { const canvas = createNodeGCanvas(800, 500); let chart; let button; + let fitted; it('chart({ autoFit: true }) should fit parent container', async () => { const { finished, ...rest } = render({ @@ -17,6 +18,7 @@ describe('chart.options.autoFit', () => { }); chart = rest.chart; button = rest.button; + fitted = rest.fitted; await finished; await sleep(20); await expect(canvas).toMatchCanvasSnapshot(dir, 'step0'); @@ -24,7 +26,7 @@ describe('chart.options.autoFit', () => { it('chart.forceFit() should fit parent container', async () => { button.dispatchEvent(new CustomEvent('click')); - await new Promise((resolve) => chart.on('afterchangesize', resolve)); + await fitted; await sleep(20); await expect(canvas).toMatchCanvasSnapshot(dir, 'step1'); }); diff --git a/__tests__/integration/snapshots/api/chart-auto-fit/step0.png b/__tests__/integration/snapshots/api/chart-auto-fit/step0.png index 8b3cf47d4b..64734e82c4 100644 Binary files a/__tests__/integration/snapshots/api/chart-auto-fit/step0.png and b/__tests__/integration/snapshots/api/chart-auto-fit/step0.png differ diff --git a/__tests__/plots/api/chart-auto-fit.ts b/__tests__/plots/api/chart-auto-fit.ts index 2101fa7c1d..ff6c583354 100644 --- a/__tests__/plots/api/chart-auto-fit.ts +++ b/__tests__/plots/api/chart-auto-fit.ts @@ -38,11 +38,14 @@ export function chartAutoFit(context) { const finished = chart.render(); + let resolve; + const fitted = new Promise((r) => (resolve = r)); + button.onclick = () => { wrapperDiv.style.width = '400px'; wrapperDiv.style.height = '500px'; - chart.forceFit(); + chart.forceFit().then(resolve); }; - return { chart, button, finished }; + return { chart, button, finished, fitted }; } diff --git a/__tests__/unit/api/chart.spec.ts b/__tests__/unit/api/chart.spec.ts index 792c9626e7..755773fa01 100644 --- a/__tests__/unit/api/chart.spec.ts +++ b/__tests__/unit/api/chart.spec.ts @@ -605,4 +605,22 @@ describe('Chart', () => { expect(interval.data()).toEqual([data[1]]); expect(line.data()).toEqual([data[1]]); }); + + it('new Chart({ autoFit: true }) should not set width and height of chart options.', async () => { + const chart = new Chart({ theme: 'classic', autoFit: true }); + chart + .interval() + .data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold'); + await chart.render(); + expect(chart.width()).toBeUndefined(); + expect(chart.height()).toBeUndefined(); + }); }); diff --git a/src/api/chart.ts b/src/api/chart.ts index 3090da812c..9ed8ab437c 100644 --- a/src/api/chart.ts +++ b/src/api/chart.ts @@ -5,7 +5,7 @@ import { debounce, deepMix, omit } from '@antv/util'; import EventEmitter from '@antv/event-emitter'; import { G2Context, render, destroy } from '../runtime'; import { ViewComposition } from '../spec'; -import { getChartSize } from '../utils/size'; +import { getContainerSize } from '../utils/size'; import { ChartEvent } from '../utils/event'; import { G2ViewTree } from '../runtime/types/options'; import { Node } from './node'; @@ -95,6 +95,13 @@ function Canvas( }); } +function sizeOf(options, container) { + const { autoFit } = options; + if (autoFit) return getContainerSize(container); + const { width = 640, height = 480 } = options; + return { width, height }; +} + export function optionsOf(node: Node): Record { const root = normalizeRoot(node); const discovered: Node[] = [root]; @@ -169,6 +176,8 @@ export class Chart extends View { private _context: G2Context; private _emitter: EventEmitter; private _options: G2ViewTree; + private _width: number; + private _height: number; constructor(options: ChartOptions) { const { container, canvas, key = G2_CHART_KEY, ...rest } = options || {}; @@ -183,22 +192,8 @@ export class Chart extends View { render(): Promise { if (!this._context.canvas) { // Init width and height. - const { - width = 640, - height = 480, - renderer, - plugins, - autoFit, - } = this.options(); - const { width: adjustedWidth, height: adjustedHeight } = getChartSize( - this._container, - autoFit, - width, - height, - ); - this.width(adjustedWidth); - this.height(adjustedHeight); - + const { renderer, plugins } = this.options(); + const { width, height } = sizeOf(this.options(), this._container); // Create canvas if it does not exist. this._context.canvas = Canvas( this._container, @@ -211,12 +206,21 @@ export class Chart extends View { return new Promise((resolve, reject) => { try { - render(this.options(), this._context, () => resolve(this), reject); + const { width, height } = sizeOf(this.options(), this._container); + this._width = width; + this._height = height; + render( + { ...this.options(), width, height }, + this._context, + () => resolve(this), + reject, + ); } catch (e) { reject(e); } }); } + /** * @overload * @returns {G2ViewTree} @@ -291,26 +295,24 @@ export class Chart extends View { } forceFit() { - const { width, height, autoFit } = this.options(); - const { width: adjustedWidth, height: adjustedHeight } = getChartSize( - this._container, - autoFit, - width, - height, - ); - if (adjustedHeight && adjustedWidth) { - this.changeSize(adjustedWidth, adjustedHeight); - } + // Don't call changeSize to prevent update width and height of options. + // @ts-ignore + this.options.autoFit = true; + this.emit(ChartEvent.BEFORE_CHANGE_SIZE); + const finished = this.render(); + finished.then(() => { + this.emit(ChartEvent.AFTER_CHANGE_SIZE); + }); + return finished; } - changeSize(adjustedWidth: number, adjustedHeight: number): Promise { - const { width, height, on } = this.options(); - if (width === adjustedWidth && height === adjustedHeight) { + changeSize(width: number, height: number): Promise { + if (width === this._width && height === this._height) { return Promise.resolve(this); } this.emit(ChartEvent.BEFORE_CHANGE_SIZE); - this.width(adjustedWidth); - this.height(adjustedHeight); + this.width(width); + this.height(height); const finished = this.render(); finished.then(() => { this.emit(ChartEvent.AFTER_CHANGE_SIZE); diff --git a/src/utils/size.ts b/src/utils/size.ts index 1cbb7c6320..27dd8b1c0e 100644 --- a/src/utils/size.ts +++ b/src/utils/size.ts @@ -31,37 +31,6 @@ export function getContainerSize(container: HTMLElement): Size { }; } -/** - * - * @description Calculate the chart size. - * @param container DOM container element. - * @param autoFit Should auto fit. - * @param width Chart width which is set by user. - * @param height Chart height which is set by user. - * @returns chart width and height. - */ -export function getChartSize( - container: HTMLElement, - autoFit: boolean, - width: number, - height: number, -): Size { - if (!autoFit) { - return { - width, - height, - }; - } - - // Get size from wrapper container. - const size = getContainerSize(container); - - return { - width: size.width, - height: size.height, - }; -} - /** * @description Calculate the real canvas size by view options. */