Skip to content

Commit

Permalink
Fixes #460: Initialise echarts with correct width and height (#464)
Browse files Browse the repository at this point in the history
* Fix initial echarts div size by using temporary render

* Remove timeout and replace with finished event

* Add tests for container size
  • Loading branch information
mobeigi authored Feb 12, 2022
1 parent 6f49a85 commit 0ab3861
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 10 deletions.
156 changes: 156 additions & 0 deletions __tests__/charts/simple-spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,160 @@ describe('chart', () => {

removeDom(div);
});

describe('container size', () => {
it('default', () => {
let instance;
const div = createDiv();
div.style.display = 'block';
div.style.width = '1200px';
div.style.height = '720px';

const Comp = <ReactECharts ref={(e) => (instance = e)} option={options} />;
render(Comp, div);

expect(instance).toBeDefined();
expect(instance.getEchartsInstance()).toBeDefined();
expect(instance.getEchartsInstance().getWidth()).toBe(1200);
expect(instance.getEchartsInstance().getHeight()).toBe(300); // default height

destroy(div);
expect(div.querySelector('*')).toBe(null);

removeDom(div);
});

describe('style', () => {
it('100% width', () => {
let instance;
const div = createDiv();
div.style.display = 'block';
div.style.width = '1200px';
div.style.height = '720px';

const style = {
width: '100%',
};

const Comp = <ReactECharts ref={(e) => (instance = e)} option={options} style={style} />;
render(Comp, div);

expect(instance).toBeDefined();
expect(instance.getEchartsInstance()).toBeDefined();
expect(instance.getEchartsInstance().getWidth()).toBe(1200);
expect(instance.getEchartsInstance().getHeight()).toBe(300); // default height

destroy(div);
expect(div.querySelector('*')).toBe(null);

removeDom(div);
});

it('100% width, 100% height', () => {
let instance;
const div = createDiv();
div.style.display = 'block';
div.style.width = '1200px';
div.style.height = '720px';

const style = {
width: '100%',
height: '100%',
};

const Comp = <ReactECharts ref={(e) => (instance = e)} option={options} style={style} />;
render(Comp, div);

expect(instance).toBeDefined();
expect(instance.getEchartsInstance()).toBeDefined();
expect(instance.getEchartsInstance().getWidth()).toBe(1200);
expect(instance.getEchartsInstance().getHeight()).toBe(720);

destroy(div);
expect(div.querySelector('*')).toBe(null);

removeDom(div);
});

it('custom width, custom height', () => {
let instance;
const div = createDiv();
div.style.display = 'block';
div.style.width = '1200px';
div.style.height = '720px';

const style = {
width: '400px',
height: '150px',
};

const Comp = <ReactECharts ref={(e) => (instance = e)} option={options} style={style} />;
render(Comp, div);

expect(instance).toBeDefined();
expect(instance.getEchartsInstance()).toBeDefined();
expect(instance.getEchartsInstance().getWidth()).toBe(400);
expect(instance.getEchartsInstance().getHeight()).toBe(150);

destroy(div);
expect(div.querySelector('*')).toBe(null);

removeDom(div);
});
});

describe('opts', () => {
it('default', () => {
let instance;
const div = createDiv();
div.style.display = 'block';
div.style.width = '1200px';
div.style.height = '720px';

const opts = {
width: null,
height: null,
};

const Comp = <ReactECharts ref={(e) => (instance = e)} option={options} opts={opts} />;
render(Comp, div);

expect(instance).toBeDefined();
expect(instance.getEchartsInstance()).toBeDefined();
expect(instance.getEchartsInstance().getWidth()).toBe(1200);
expect(instance.getEchartsInstance().getHeight()).toBe(300); // default height

destroy(div);
expect(div.querySelector('*')).toBe(null);

removeDom(div);
});

it('custom width, custom height', () => {
let instance;
const div = createDiv();
div.style.display = 'block';
div.style.width = '1200px';
div.style.height = '720px';

const opts = {
width: 400,
height: 150,
};

const Comp = <ReactECharts ref={(e) => (instance = e)} option={options} opts={opts} />;
render(Comp, div);

expect(instance).toBeDefined();
expect(instance.getEchartsInstance()).toBeDefined();
expect(instance.getEchartsInstance().getWidth()).toBe(400);
expect(instance.getEchartsInstance().getHeight()).toBe(150);

destroy(div);
expect(div.querySelector('*')).toBe(null);

removeDom(div);
});
});
});
});
53 changes: 43 additions & 10 deletions src/core.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,40 @@ export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
this.dispose();
}

/*
* initialise an echarts instance
*/
public async initEchartsInstance(): Promise<ECharts> {
return new Promise((resolve) => {
// create temporary echart instance
this.echarts.init(this.ele, this.props.theme, this.props.opts);
const echartsInstance = this.getEchartsInstance();

echartsInstance.on('finished', () => {
// get final width and height
const width = this.ele.clientWidth;
const height = this.ele.clientHeight;

// dispose temporary echart instance
this.echarts.dispose(this.ele);

// recreate echart instance
// we use final width and height only if not originally provided as opts
const opts = {
width,
height,
...this.props.opts,
};
resolve(this.echarts.init(this.ele, this.props.theme, opts));
});
});
}

/**
* return the echart object
* 1. if exist, return the existed instance
* 2. or new one instance
* return the existing echart object
*/
public getEchartsInstance(): ECharts {
return this.echarts.getInstanceByDom(this.ele) || this.echarts.init(this.ele, this.props.theme, this.props.opts);
return this.echarts.getInstanceByDom(this.ele);
}

/**
Expand All @@ -109,19 +136,22 @@ export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
/**
* render a new echarts instance
*/
private renderNewEcharts() {
private async renderNewEcharts() {
const { onEvents, onChartReady } = this.props;

// 1. new echarts instance
// 1. init echarts instance
await this.initEchartsInstance();

// 2. update echarts instance
const echartsInstance = this.updateEChartsOption();

// 2. bind events
// 3. bind events
this.bindEvents(echartsInstance, onEvents || {});

// 3. on chart ready
// 4. on chart ready
if (isFunction(onChartReady)) onChartReady(echartsInstance);

// 4. on resize
// 5. on resize
if (this.ele) {
bind(this.ele, () => {
this.resize();
Expand Down Expand Up @@ -176,7 +206,10 @@ export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
// resize should not happen on first render as it will cancel initial echarts animations
if (!this.isInitialResize) {
try {
echartsInstance.resize();
echartsInstance.resize({
width: 'auto',
height: 'auto',
});
} catch (e) {
console.warn(e);
}
Expand Down

0 comments on commit 0ab3861

Please sign in to comment.