Apache ECharts 5.3.0 特性
Apache ECharts 5.3.0 在动画表现力、渲染性能和服务端渲染方面进行了重大改进。 它还添加了社区期待已久的功能,例如多轴刻度的自动对齐、提示框值格式化和地图投影。
关键帧动画
之前,ECharts 动画主要集中在创建、更新和删除元素的过渡动画,这些动画通常只有开始状态和结束状态。 为了表达更复杂的动画,我们在 5.3.0 中为自定义系列和图形组件引入了新的关键帧动画。
这是一个通过关键帧动画实现的简单呼吸动画效果
option = { graphic: { type: 'circle', shape: { r: 100 }, left: 'center', top: 'center', keyframeAnimation: [ { duration: 3000, loop: true, keyframes: [ { percent: 0.5, easing: 'sinusoidalInOut', scaleX: 0.1, scaleY: 0.1 }, { percent: 1, easing: 'sinusoidalInOut', scaleX: 1, scaleY: 1 } ] } ] } };
在关键帧动画中,您可以配置动画的持续时间、延迟、缓动、是否循环,以及每个关键帧的位置、缓动和图形属性。 您还可以同时为每个元素设置多个具有不同配置的关键帧动画。 灵活的配置使我们能够实现非常复杂的动画效果,以下是可以使用关键帧动画的几种场景。
自定义加载动画
ECharts 默认有一个内置的加载动画,可以通过调用 showLoading
来显示。 社区中经常会有人询问更多的加载动画效果。 现在,使用关键帧动画,我们可以使用带有关键帧动画的 graphic 组件来实现我们想要的任何加载动画效果。
这是一个文本描边动画的示例。
option = { graphic: { elements: [ { type: 'text', left: 'center', top: 'center', style: { text: 'Apache ECharts', fontSize: 40, fontWeight: 'bold', lineDash: [0, 200], lineDashOffset: 0, fill: 'transparent', stroke: '#000', lineWidth: 1 }, keyframeAnimation: { duration: 3000, loop: true, keyframes: [ { percent: 0.7, style: { fill: 'transparent', lineDashOffset: 200, lineDash: [200, 0] } }, { // Stop for a while. percent: 0.8, style: { fill: 'transparent' } }, { percent: 1, style: { fill: 'black' } } ] } } ] } };
或为柱子添加动画。
const columns = []; for (let i = 0; i < 7; i++) { columns.push({ type: 'rect', x: i * 20, shape: { x: 0, y: -40, width: 10, height: 80 }, style: { fill: '#5470c6' }, keyframeAnimation: { duration: 1000, delay: i * 200, loop: true, keyframes: [ { percent: 0.5, scaleY: 0.1, easing: 'cubicIn' }, { percent: 1, scaleY: 1, easing: 'cubicOut' } ] } }); } option = { graphic: { elements: [ { type: 'group', left: 'center', top: 'center', children: columns } ] } };
扩展图表中更丰富的动画效果
带有动画效果的散点图一直是 ECharts 的一个特点。 开发人员可以使用 effectScatter 系列来实现带有涟漪效果的动态散点图,这使图表更有趣,也用于突出显示用户。 与加载动画一样,开发人员经常要求更多的动画效果。 现在,我们可以在 自定义 系列中使用关键帧动画来实现更复杂的效果。
例如,以下示例使用跳跃效果动画显示自定义系列在 SVG 地图上绘制的图钉,并带有涟漪动画。
fetch( 'https://fastly.jsdelivr.net/gh/apache/echarts-website@asf-site/examples/data/asset/geo/Map_of_Iceland.svg' ) .then(response => response.text()) .then(svg => { echarts.registerMap('iceland_svg', { svg: svg }); option = { geo: { map: 'iceland_svg', left: 0, right: 0 }, series: { type: 'custom', coordinateSystem: 'geo', geoIndex: 0, zlevel: 1, data: [ [488, 459, 100], [770, 757, 30], [1180, 743, 80], [894, 1188, 61], [1372, 477, 70], [1378, 935, 81] ], renderItem(params, api) { const coord = api.coord([ api.value(0, params.dataIndex), api.value(1, params.dataIndex) ]); const circles = []; for (let i = 0; i < 5; i++) { circles.push({ type: 'circle', shape: { cx: 0, cy: 0, r: 30 }, style: { stroke: 'red', fill: 'none', lineWidth: 2 }, // Ripple animation keyframeAnimation: { duration: 4000, loop: true, delay: (-i / 4) * 4000, keyframes: [ { percent: 0, scaleX: 0, scaleY: 0, style: { opacity: 1 } }, { percent: 1, scaleX: 1, scaleY: 0.4, style: { opacity: 0 } } ] } }); } return { type: 'group', x: coord[0], y: coord[1], children: [ ...circles, { type: 'path', shape: { d: 'M16 0c-5.523 0-10 4.477-10 10 0 10 10 22 10 22s10-12 10-22c0-5.523-4.477-10-10-10zM16 16c-3.314 0-6-2.686-6-6s2.686-6 6-6 6 2.686 6 6-2.686 6-6 6z', x: -10, y: -35, width: 20, height: 40 }, style: { fill: 'red' }, // Jump animation. keyframeAnimation: { duration: 1000, loop: true, delay: Math.random() * 1000, keyframes: [ { y: -10, percent: 0.5, easing: 'cubicOut' }, { y: 0, percent: 1, easing: 'bounceOut' } ] } } ] }; } } }; myChart.setOption(option); });
加载 Lottie 动画
为了充分利用新的关键帧动画的功能,ECharts 团队的 Yi Shen 编写了一个 Lottie 动画解析库,该库可以将 Lottie 动画文件解析为 ECharts 图形格式以进行渲染。 结合 Lottie 的表现力,我们可以为我们的项目引入更多令人惊叹的动画。
图形组件过渡动画
我们在 5.0 中为自定义系列中返回的元素提供了更灵活的过渡动画配置。transition
、enterFrom
和 leaveTo
配置项允许您配置每个元素的哪些属性将具有过渡动画,以及在创建和删除图形时如何进行动画处理。 这是一个例子。
function renderItem() {
//...
return {
//...
x: 100,
// 'style', 'x', 'y' will be animated
transition: ['style', 'x', 'y'],
enterFrom: {
style: {
// Fade in
opacity: 0
},
// Fly in from the left
x: 0
},
leaveTo: {
// Fade out
opacity: 0
},
// Fly out to the right
x: 200
};
}
在 5.3.0 中,我们将这些过渡动画的配置扩展到了图形组件,并进行了额外的增强。
如果您不想写出每个要动画的属性,您现在可以直接配置 transition: 'all'
来动画所有属性。
我们还添加了 enterAnimation
、updateAnimation
和 leaveAnimation
来分别配置每个图形的进入、更新和退出动画的 duration
、delay
和 easing
。 渐变颜色现在也支持动画。
新的 SVG 渲染器
在 5.3.0 中,我们重构了我们的 SVG 渲染器,它提供了 2 倍 ~ 10 倍的性能提升,在某些特殊场景下甚至可以达到数十倍。
之前,我们直接从渲染队列到 DOM 更新 SVG 渲染器,但由于 zrender 的图形属性与 DOM 不是一一对应的,因此我们必须在中间实现非常复杂的 diff 逻辑,这很容易出错并且在某些情况下无法提供最佳性能。 在此版本中,我们首先将完整渲染重建为 VDOM,然后将 VDOM 补丁到 DOM 以完成渲染。 完整渲染避免了复杂的 diff 逻辑可能引起的潜在错误,并且 VDOM 和 DOM 之间的一一对应关系确保了在修补时更新最小,从而带来了巨大的性能提升。
此示例让您直观地了解性能的提升。 在 SVG 模式下拖动图表时,新版本比之前的版本流畅得多。
5.2.2 (之前) | 5.3.0 (之后) |
---|---|
除了性能提升之外,我们还可以使用渲染的 VDOM 做更多的事情,例如服务器端渲染,这将在下面描述。
零依赖的服务器端渲染
在之前的版本中,ECharts 也可以实现服务器端渲染,但它必须依赖 node-canvas,或者如果您使用 SVG 模式来模拟 DOM 环境,则依赖 JSDOM。 这些依赖不仅带来了额外的尺寸和使用要求,而且还影响了性能。
这个新的 SVG 渲染器允许我们从中间渲染的 VDOM 获取字符串,从而带来完全零依赖的服务器端渲染,并输出更精细的集成 CSS 动画的 SVG 字符串。
const echarts = require('echarts');
// In SSR mode the first parameter does not need to be passed in as a DOM object
const chart = echarts.init(null, null, {
renderer: 'svg', // must use SVG mode
ssr: true, // enable SSR
width: 400, // need to specify height and width
height: 300
});
// setOption as normal
chart.setOption({
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}
]
});
// Output string
const svgStr = chart.renderToSVGString();
自定义地图投影
地图一直是 ECharts 中非常广泛使用的组件。 通常,地图组件使用 GeoJSON 格式的数据,其中存储了纬度和经度。 然后,ECharts 计算适当的显示区域,并将纬度和经度线性映射到该区域。 这是投影地图的最简单方法。 但是,简单的线性投影不适用于复杂的地图场景,例如使用 Albers 投影来解决线性投影中的失真问题,或者将太平洋放在世界地图的中间等等。
因此,在 5.3.0 中,我们引入了扩展地图投影。 它通过 project
和 unproject
方法告诉 ECharts 如何投影坐标以及如何从投影坐标计算纬度和经度。 以下是使用墨卡托投影的简单示例。
series = {
type: 'map',
projection: {
project: point => [
(point[0] / 180) * Math.PI,
-Math.log(Math.tan((Math.PI / 2 + (point[1] / 180) * Math.PI) / 2))
],
unproject: point => [
(point[0] * 180) / Math.PI,
((2 * 180) / Math.PI) * Math.atan(Math.exp(point[1])) - 90
]
}
};
除了实现我们自己的投影公式外,我们还可以使用第三方库(如 d3-geo)提供的投影实现。
const projection = d3.geoConicEqualArea();
// ...
series = {
type: 'map',
projection: {
project: point => projection(point),
unproject: point => projection.invert(point)
}
};
结合 5.2 中添加的新的全局过渡动画功能,我们可以动画显示不同投影效果之间的过渡:!
除了地图投影外,我们还在本版本中对地图进行了以下两项增强。
- 为 GeoJSON 数据提供了
'LineString'
和'MultiLineString'
支持。 - 将默认标签位置的计算从边界框的中心更改为最大区域的质心,以获得更准确的结果。
多轴刻度对齐
多轴刻度对齐是社区中长期存在的要求,我们可以在社区中看到许多关于如何在 ECharts 中实现轴对齐的文章,这通常很麻烦并且有限制。
在 5.3.0 中,我们最终引入了对齐 'value'
和 'log'
轴上的刻度的功能。 您可以在需要对齐的轴中配置 alignTicks: true
。 然后,轴将根据第一个轴的刻度调整其自身的刻度,从而实现自动对齐。
option = { tooltip: { trigger: 'axis' }, legend: {}, xAxis: [ { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], axisPointer: { type: 'shadow' } } ], yAxis: [ { type: 'value', name: 'Precipitation', alignTicks: true, axisLabel: { formatter: '{value} ml' } }, { type: 'value', name: 'Temperature', axisLabel: { formatter: '{value} °C' } } ], series: [ { name: 'Evaporation', type: 'bar', // prettier-ignore data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3] }, { name: 'Precipitation', type: 'bar', // prettier-ignore data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3] }, { name: 'Temperature', type: 'line', yAxisIndex: 1, data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2] } ] };
禁用高亮和选中状态
ECharts 中的 emphasis
状态在鼠标悬停在元素上时为用户提供反馈,但在包含大量元素的图表中,高亮动画可能会导致性能问题。 特别是,由 tooltip 或 legend 组件联动触发的高亮可以同时高亮显示多个元素。
因此,在此版本中,我们添加了 emphasis.disabled
配置。 如果您不需要高亮反馈并且您担心交互性,您可以使用此选项禁用 emphasis
状态。
对于 select
状态,我们还添加了 select.disabled
。 此选项可用于配置某些数据为不可选。
支持选择整个系列
从 5.3.0 开始,我们支持将 selectedMode
配置为 'series'
以启用选择系列中的所有数据。
提示框中的值格式化
当用户悬停在数据项上时,提示框可用于显示有关数据项的更多详细信息。 ECharts 还提供了 formatter
回调函数,使开发人员可以更灵活地自定义提示框的内容。
但是,我们发现大多数情况下,开发人员只需要格式化提示框的值部分,例如固定精度、以 $
为前缀等。 以前,为了格式化数字,开发人员必须使用 formatter
重写提示框的整个内容。 特别是在 5.0 之后,ECharts 提示框变得更加复杂和美观,因此重写它们变得成本高昂且难以实现默认结果。
因此,在此版本中,我们为提示框添加了 valueFormatter
配置,用于格式化值部分。
与轴对齐示例一样,我们可以在提示框的值部分添加 °C 和 ml 后缀。
option = { tooltip: { trigger: 'axis' }, legend: {}, xAxis: [ { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], axisPointer: { type: 'shadow' } } ], yAxis: [ { type: 'value', name: 'Precipitation', alignTicks: true, axisLabel: { formatter: '{value} ml' } }, { type: 'value', name: 'Temperature', axisLabel: { formatter: '{value} °C' } } ], series: [ { name: 'Evaporation', type: 'bar', tooltip: { valueFormatter: value => value + ' ml' }, // prettier-ignore data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3] }, { name: 'Precipitation', type: 'bar', tooltip: { valueFormatter: value => value + ' ml' }, // prettier-ignore data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3] }, { name: 'Temperature', type: 'line', yAxisIndex: 1, tooltip: { valueFormatter: value => value + ' °C' }, data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2] } ] };
每个系列都可以根据自身的值格式配置自己的 valueFormatter
。
更灵活的扇形角半径
在 5.0 中,我们为扇形添加了圆角配置,这可以使饼图和旭日图更有趣。 之前,我们仅单独支持内半径和外半径,这次我们更进一步,支持配置扇形的四个角具有不同的角半径,从而带来更灵活的显示。
option = { tooltip: { trigger: 'item' }, legend: { top: '5%', left: 'center' }, series: [ { name: 'Access From', type: 'pie', radius: ['30%', '70%'], roseType: 'angle', itemStyle: { borderRadius: [20, 5, 5, 10], borderColor: '#fff', borderWidth: 2 }, label: { show: false }, data: [ { value: 800, name: 'Search Engine' }, { value: 735, name: 'Direct' }, { value: 580, name: 'Email' }, { value: 484, name: 'Union Ads' }, { value: 400, name: 'Video Ads' } ] } ] };
饼图的复杂标签优化
饼图一直是 ECharts 中标签显示最复杂的图表之一。我们长期以来一直在优化饼图标签的布局和显示。
这次,我们对使用文本换行、背景颜色、富文本和其他复杂布局的饼图标签进行了深度优化。在自适应宽度、容器溢出、引导线计算等方面,都比以前有了更好的效果。
5.2.2 (之前) | 5.3.0 (之后) |
---|---|
柱状图大型模式优化
在数据量较大(> 2k)的情况下,我们支持通过开启 large 模式来加速柱状图的渲染并提高交互性能。但之前,large 模式下柱状图的布局比较简单,不支持多个系列堆叠后的布局。在 5.3.0 中,我们优化了 large 模式的布局,使其与正常模式保持一致。通过开启 large,我们可以在更多场景下优化柱状图的性能。
此外,优化的柱状图布局还修复了在非线性轴(如对数轴)上堆叠不正确的错误。
重大变更
registerMap
和 getMap
方法需要在导入地图图表后才能使用
为了减小最小包的大小,我们从核心模块中移除了地图数据管理方法 getMap
和 registerMap
。
如果您是只导入必要的图表和组件,您需要确保在可以使用 registerMap
注册地图数据之前,已经导入了 GeoComponent
或 MapChart
。
import * as echarts from 'echarts/core';
import { MapChart } from 'echarts/charts';
echarts.use([MapChart]);
// You must import the MapChart with the `use` method before you can register the map with registerMap
echarts.registerMap('world', worldJSON);
如果您使用 import * as echarts from 'echarts'
导入整个包,此更改不会对您产生任何影响。
移除折线图中默认的加粗强调效果
我们在 5.0 版本中为折线图引入了默认的加粗强调效果,但社区反馈说,在很多场景下,这种效果看起来并不好。因此,在这个版本中,我们将此效果从默认开启改为默认关闭。您可以通过以下方式启用它:
series = {
type: 'line',
//...
emphasis: {
lineStyle: {
width: 'bolder'
}
}
};
完整更新日志
查看更新日志