数据过渡

Apache EChartsTM 在添加、更新和删除数据时,会对位置、缩放、形状应用过渡。这使得图表更加平滑,并更好地展示数据之间的关系。通常情况下,开发者不需要担心如何使用动画,只需使用 setOption 来更新数据,ECharts 会找出最后的数据差异并自动应用最合适的过渡动画。

例如,以下示例展示了饼图数据定时更新时的过渡。

function makeRandomData() {
  return [
    {
      value: Math.random(),
      name: 'A'
    },
    {
      value: Math.random(),
      name: 'B'
    },
    {
      value: Math.random(),
      name: 'C'
    }
  ];
}
option = {
  series: [
    {
      type: 'pie',
      radius: [0, '50%'],
      data: makeRandomData()
    }
  ]
};

setInterval(() => {
  myChart.setOption({
    series: {
      data: makeRandomData()
    }
  });
}, 2000);
实时

过渡配置

由于添加和更新数据通常需要不同的动画,例如我们希望数据更新动画更短,ECharts 区分了这两种动画配置。

  • 对于添加数据,我们应用进入动画,使用 animationDurationanimationEasinganimationDelay 分别配置动画的持续时间、缓动和延迟。
  • 对于更新数据,我们将应用更新动画,使用 animationDurationUpdateanimationEasingUpdateanimationDelayUpdate 分别配置动画的持续时间、缓动和延迟。

如你所见,更新动画配置是带有 Update 后缀的进入动画配置。

每次使用 ECharts 中的 setOption,数据都会与上次更新的数据进行比较,并根据比较结果对数据执行三种状态:添加、更新和删除。此比较基于数据的“名称”,例如,如果上次更新有三个“名称”为“A”、“B”、“C”,而新更新已变为“B”、“C”、“D”,则数据“B”、“C”将被更新,数据“A”将被删除,数据“D”将被添加。如果是第一次 setOption,则由于没有旧数据,所有数据都将被添加。根据这三种状态,ECharts 将分别应用进入动画、更新动画和离开动画。

所有这些配置都可以针对所有系列和组件在 option 的顶级设置,或针对每个系列单独设置。

如果我们想关闭动画,我们可以简单地将 option.animation 设置为 false。

动画持续时间

animationDuration 和 animationDurationUpdate 用于设置动画的持续时间(以毫秒为单位)。设置较长的动画持续时间可以让用户更清楚地看到过渡动画的效果,但我们也需要注意,时间太长可能会让用户在等待动画完成时失去耐心。

将设置设置为 0 将关闭动画,当我们只想关闭进入动画或更新动画时,可以通过单独将相应配置设置为 0 来实现。

动画缓动

animationEasing 和 animationEasingUpdate 配置项用于设置动画的缓动函数,该函数输入动画时间并输出动画进度。

(t: number) => number;

ECharts 中内置了“cubicIn”和“cubicOut”等常见的动画缓动函数,可以直接使用。

内置缓动函数。

动画延迟

animationDelay 和 animationDelayUpdate 用于设置动画延迟开始的时间,通常我们会使用回调函数为不同的数据设置不同的延迟,以达到交错动画的效果。

var xAxisData = [];
var data1 = [];
var data2 = [];
for (var i = 0; i < 100; i++) {
  xAxisData.push('A' + i);
  data1.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5);
  data2.push((Math.cos(i / 5) * (i / 5 - 10) + i / 6) * 5);
}
option = {
  legend: {
    data: ['bar', 'bar2']
  },
  xAxis: {
    data: xAxisData,
    splitLine: {
      show: false
    }
  },
  yAxis: {},
  series: [
    {
      name: 'bar',
      type: 'bar',
      data: data1,
      emphasis: {
        focus: 'series'
      },
      animationDelay: function(idx) {
        return idx * 10;
      }
    },
    {
      name: 'bar2',
      type: 'bar',
      data: data2,
      emphasis: {
        focus: 'series'
      },
      animationDelay: function(idx) {
        return idx * 10 + 100;
      }
    }
  ],
  animationEasing: 'elasticOut',
  animationDelayUpdate: function(idx) {
    return idx * 5;
  }
};
实时

动画性能优化

当数据量特别大的时候,运行动画可能会出现性能问题,此时我们可以通过设置 animation: false 来关闭动画。

对于数据量动态变化的图表,我们推荐使用 animationThreshold 配置项,可以让 ECharts 在 Canvas 中图形数量超过这个阈值时自动关闭动画,以提升绘制性能。这个值通常是一个经验值,ECharts 通常能够实时渲染上千个图形(我们默认给出的值也是 2000),但如果你的图表比较复杂,或者你的用户环境比较恶劣,页面上同时运行着很多其他复杂的代码,那么可以适当调低这个值,以保证整个应用的流畅性。

监听动画结束

有时候我们想要获取当前渲染的结果,如果没有使用动画,ECharts 会在 setOption 之后直接进行渲染,我们可以使用 getDataURL 方法同步获取渲染结果。

const chart = echarts.init(dom);
chart.setOption({
  animation: false
  //...
});
// can be executed directly and synchronously
const dataUrl = chart.getDataURL();

但是如果图表有动画,此时直接执行 getDataURL 会得到动画开始时的画面,而不是最终结果。所以我们需要知道动画何时结束,然后执行 getDataURL 来获取结果。

如果你确定了动画的持续时间,一个比较简单粗暴的方式是根据动画的持续时间,使用 setTimeout 来延迟执行

chart.setOption({
  animationDuration: 1000
  //...
});
setTimeout(() => {
  const dataUrl = chart.getDataURL();
}, 1000);

另外,我们可以使用 ECharts 提供的 rendered 事件来判断 ECharts 是否已经完成动画并停止渲染

chart.setOption({
  animationDuration: 1000
  //...
});

function onRendered() {
  const dataUrl = chart.getDataURL();
  // ...
  // This event will also be triggered if there is a subsequent interaction and the interaction is redrawn, so it needs to be removed when you're done using it
  chart.off('rendered', onRendered);
}
chart.on('rendered', onRendered);

贡献者 在 GitHub 上编辑此页面

pissang pissang