antvis/G2

chart resize 数据重置 #4492

shichuanpo posted onGitHub

5.0.0-beta.4版本: chart.render之后 changeData, resize之后图表数据被重置到第一次声明的数据。

复现步骤: 官方案例区间条形图 替换以下代码

import { Chart } from '@antv/g2';

const chart = new Chart({ container: 'container', autoFit: true, paddingLeft: 60, });

const aaa = chart .interval() .data([ { month: 'Jan.', profit: 387264, start: 0, end: 387264 }, { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 } ]) .encode('x', 'month') .encode('y', ['end', 'start']) .encode('color', (d) => d.month === 'Total' ? 'Total' : d.profit > 0 ? 'Increase' : 'Decrease', ) .axis('y', { labelFormatter: '~s' });

chart.render(); aaa.changeData([ { month: 'Jan.', profit: 387264, start: 0, end: 387264 }, { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 }, { month: 'Mar.', profit: 638075, start: 1159360, end: 1797435 }, { month: 'Apr.', profit: -211386, start: 1797435, end: 1586049 }, { month: 'May', profit: -138135, start: 1586049, end: 1447914 }, { month: 'Jun', profit: -267238, start: 1447914, end: 1180676 }, { month: 'Jul.', profit: 431406, start: 1180676, end: 1612082 }, { month: 'Aug.', profit: 363018, start: 1612082, end: 1975100 }, { month: 'Sep.', profit: -224638, start: 1975100, end: 1750462 }, { month: 'Oct.', profit: -299867, start: 1750462, end: 1450595 }, { month: 'Nov.', profit: 607365, start: 1450595, end: 2057960 }, { month: 'Dec.', profit: 1106986, start: 2057960, end: 3164946 }, { month: 'Total', start: 0, end: 3164946 }, ])


出现问题的原因是 chart.render 是一个异步的函数,aaa.changeDatachart.render 还没有执行完成的时候更新会出现问题。解决办法应该是:等待 chart.render 结束之后在去更新数据。

目前有如下几种办法:

  • 设置定时器:简单但是渲染完成的时间和动画以及渲染图表本身有关。

import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
  paddingLeft: 60,
});

const aaa = chart
  .interval()
  .data([
    { month: 'Jan.', profit: 387264, start: 0, end: 387264 },
    { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 },
  ])
  .encode('x', 'month')
  .encode('y', ['end', 'start'])
  .encode('color', (d) =>
    d.month === 'Total' ? 'Total' : d.profit > 0 ? 'Increase' : 'Decrease',
  )
  .axis('y', { labelFormatter: '~s' });

chart.render();

setTimeout(() => {
  aaa.changeData([
    { month: 'Jan.', profit: 387264, start: 0, end: 387264 },
    { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 },
    { month: 'Mar.', profit: 638075, start: 1159360, end: 1797435 },
    { month: 'Apr.', profit: -211386, start: 1797435, end: 1586049 },
    { month: 'May', profit: -138135, start: 1586049, end: 1447914 },
    { month: 'Jun', profit: -267238, start: 1447914, end: 1180676 },
    { month: 'Jul.', profit: 431406, start: 1180676, end: 1612082 },
    { month: 'Aug.', profit: 363018, start: 1612082, end: 1975100 },
    { month: 'Sep.', profit: -224638, start: 1975100, end: 1750462 },
    { month: 'Oct.', profit: -299867, start: 1750462, end: 1450595 },
    { month: 'Nov.', profit: 607365, start: 1450595, end: 2057960 },
    { month: 'Dec.', profit: 1106986, start: 2057960, end: 3164946 },
    { month: 'Total', start: 0, end: 3164946 },
  ]);
}, 1000);
  • 监听 afterrender 事件:chart.changeData 又会触发 afterrender 事件,需要特殊处理。
import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
  paddingLeft: 60,
});

const aaa = chart
  .interval()
  .data([
    { month: 'Jan.', profit: 387264, start: 0, end: 387264 },
    { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 },
  ])
  .encode('x', 'month')
  .encode('y', ['end', 'start'])
  .encode('color', (d) =>
    d.month === 'Total' ? 'Total' : d.profit > 0 ? 'Increase' : 'Decrease',
  )
  .axis('y', { labelFormatter: '~s' });

let rerender = false;
chart.on('afterrender', () => {
  if (rerender) return;
  rerender = true;
  aaa.changeData([
    { month: 'Jan.', profit: 387264, start: 0, end: 387264 },
    { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 },
    { month: 'Mar.', profit: 638075, start: 1159360, end: 1797435 },
    { month: 'Apr.', profit: -211386, start: 1797435, end: 1586049 },
    { month: 'May', profit: -138135, start: 1586049, end: 1447914 },
    { month: 'Jun', profit: -267238, start: 1447914, end: 1180676 },
    { month: 'Jul.', profit: 431406, start: 1180676, end: 1612082 },
    { month: 'Aug.', profit: 363018, start: 1612082, end: 1975100 },
    { month: 'Sep.', profit: -224638, start: 1975100, end: 1750462 },
    { month: 'Oct.', profit: -299867, start: 1750462, end: 1450595 },
    { month: 'Nov.', profit: 607365, start: 1450595, end: 2057960 },
    { month: 'Dec.', profit: 1106986, start: 2057960, end: 3164946 },
    { month: 'Total', start: 0, end: 3164946 },
  ]);
});

chart.render();
  • chart.render 返回 Promise(这个功能还没有实现)
chart.render().finished.then(() => {
  aaa.changeData([
    { month: 'Jan.', profit: 387264, start: 0, end: 387264 },
    { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 },
    { month: 'Mar.', profit: 638075, start: 1159360, end: 1797435 },
    { month: 'Apr.', profit: -211386, start: 1797435, end: 1586049 },
    { month: 'May', profit: -138135, start: 1586049, end: 1447914 },
    { month: 'Jun', profit: -267238, start: 1447914, end: 1180676 },
    { month: 'Jul.', profit: 431406, start: 1180676, end: 1612082 },
    { month: 'Aug.', profit: 363018, start: 1612082, end: 1975100 },
    { month: 'Sep.', profit: -224638, start: 1975100, end: 1750462 },
    { month: 'Oct.', profit: -299867, start: 1750462, end: 1450595 },
    { month: 'Nov.', profit: 607365, start: 1450595, end: 2057960 },
    { month: 'Dec.', profit: 1106986, start: 2057960, end: 3164946 },
    { month: 'Total', start: 0, end: 3164946 },
  ]);
});
posted by pearmini over 2 years ago

如果 render 是异步,就用 promise 吧!

posted by hustcc over 2 years ago

我指的是changeData之后,数据渲染对了。 然后改变窗口大小(触发resize事件),重新渲染之后会回到初始声明的数据。

posted by shichuanpo over 2 years ago

我指的是changeData之后,数据渲染对了。 然后改变窗口大小(触发resize事件),重新渲染之后会回到初始声明的数据。

ok,理解错了,我去排查一下

posted by pearmini over 2 years ago

G2 内部是通过一个 render(options, context) 去渲染图表的,chart.render 是调用该 render 方法。目前监听 resize 事件是在 render 方法里面监听的,这导致 window resize 支持触发了 render 函数,而不是 chart.render 方法,所以配置项没有更新。

这里的解决办法是:

  • chart 同样监听 resize 事件,并且响应对应的事件。
  • 移除 render 监听 resize 事件。
posted by pearmini over 2 years ago

Fund this Issue

$0.00
Funded

Pull requests