除了Apache ECharts 5 系列教程(3)交互能力之外,我们也非常重视开发者的体验。
我们希望 Apache ECharts 默认足够强大好用,让开发者无需为数据处理等问题分心,更高效地专注在用图表讲故事这件事上。于是,我们在 Apache ECharts 5 中,用 TypeScript 重构了整个项目,帮助项目的维护者以及使用的开发者在开发过程中更容易尽早发现类型错误。另一方面,这也降低了项目维护的门槛,改善了开发维护的效率。我们希望借助这次重构,能够吸引更多的开发者成为 Apache ECharts 的维护者。接下来就让我们具体介绍 ECharts 5 在改善开发者体验方面做了哪些改进。
开发体验
数据集
数据转换,也就是 data transform,是 ECharts 5 新支持的 API 和配置项集合。
其目的是,把常见的数据转换处理的逻辑,内置实现或者由第三方插件提供,开发者可以用统一的声明方式,来使用这些功能。
那么我们先来看一个例子:
最左侧是原始数据,是一个二维表,每一行是一个数据项,比如每一行表示,1800 年 澳大利亚的人均收入、寿命、人口是多少,1800 年 加拿大的人均收入、寿命、人口是多少,1810 年 澳大利亚的这些数据是多少,等等……
对这样的数据进行可视化的时候,我们经常并不会用上所有数据,比如可以去掉早期不准确的数据,也可能需要先对数据进行一定的计算再绘图,比如按照国家进行聚合,得到最大最小值、均值、分位点等。图中举的例子,先对数据进行了过滤,只取 1950 年后的数据,然后按国家进行聚合,算出人均收入的最大最小值、分位点,最后进行排序。这一切做完后,才绘图,绘制出盒须图,以观察不同国家,在 1950 年后的,收入状况。
数据转换,也就是 data-transform 这节,关注的就是,数据处理的过程,怎么实现,怎么使用。
事实上,之前我们往往会需要自己写数据处理代码完成上述这些数据转换,自己处理原始数据,再输入到 ECharts 中,如上图左侧的灰色部分。虽然自己写的处理代码各异,但是不少处理逻辑是类同的,比如,过滤、排序、聚合等等。
ECharts 5 试图把这里一些常用的处理逻辑,内置实现或者由第三方插件形式实现,避免了开发者重复做这些工作,如上图右侧的橙色部分。并且提供了统一的声明式配置方式。
最开始提及的例子,用数据转换来实现,会如左边这样的配置。ECharts 5 里,数据转换器,配置在数据集(也就是 dataset)中。如图示例中,dataset 里最上面一项,是原始数据。
接下来就是数据转换器的配置,其中首先使用 echarsts 内置的 filter transformer,筛选出 1950 年后的数据,然后使用一个第三方的 aggregate transformer,能计算出每个国家这些年的中位数,分位点,最大值,最小值,最后排一下序。
然后,就可以配置系列,基于数据转换的结果,画出图表。我们看到的例子,使用的是盒须图,也就是 boxplot 绘制数据,它直接表达了每个国家的分位点,最大最小值。当然我们也可以使用其他类型的图表来进行绘制,比如用柱状图绘制最大值。
并且,以声明式方式配置数据变换后,对于分析数据,也带来了一定程度的方便性。
如这个动图所示,在左侧修改数据转换器的参数配置、以及系列的参数配置,右侧能得到相应的计算结果。
为了不让内置代码变得过于庞大,我们只内置了过滤、排序等几个最常用的数据转换器,然后通过插件形式提供更多统计的转换功能。这些大家都可以在 ECharts-stat 中获取。ECharts-stat 中提供了拟合回归线,简单聚类等等数据转换器,他们可以注册进 ECharts 。
这里是一个直方图的例子。使用了散点图,绘制原始数据。数据转换器生成的直方图,用两组柱状图绘制。
这是一个回归线的例子。使用了散点图,绘制原始数据。而数据转换器生成的回归线,由另一个折线图系列绘制。
这是一个简单聚类的例子,使用了 visualMap 组件,来生成不同集蔟的颜色。
国际化
从 ECharts 开源以来 GitHub 上能找到的最早的国际化相关 issue 是在2014年提出的。长久以来,社区内的确有很强烈的需求。不完全统计,国际化相关的 issue 有不下20个。需求强烈和历史悠久促使我们开始了升级 ECharts 原有的国际化方案,采用的是根据不同的语言参数打包出不同的部署文件的形式。
从上图可以看到,对于支持的语言,最终会生成多个echerts部署文件。这种方式,使动态的语言和静态的代码包绑定在一起。使用的时候只能通过重新加载不同语言版本的 ECharts 代码来达到切换语言的目的,不太方便。老版本的实现里为了切换语言,要重新加载不同语言的 ECharts 包。
而在 EChart5 里,动态的语言包和静态的代码包分离开来。切换语言的时候,只需要加载相应语言包。通过类似挂载 theme 的方式,使用 registerLocale
函数挂载语言包对象,重新初始化后就完成了语言的切换。同时,为了简化敲一次命令生成一个指定语言的包的繁琐操作, ECharts5 中的语言包是自动打包生成的。你也可以通过 build:i18n
命令,手动一次性生成所有语言包。
另外,打包生成的每种语言包都会生成类似上图的两个语言包 其中,lang 包是一个包含了 registerLocale
函数的供直接加载使用的包。使用时,只需要直接加载即可,无需再手动注册。而 lang-obj 包提供了纯语言包对象,供用户灵活改造并自行注册。当前除了默认支持的英文和简体中文以外 也感谢社区的同学贡献的法语,泰语,芬兰语,西班牙语,日语,等语言包。
也欢迎大家贡献,继续丰富我们的国际化语言包,使 ECharts 成为全球化的组件库!
TypeScript 重构
ECharts 5 所做的第一个工作是,把整个的代码库,从 JS 改成了 TS。
这件事情是个比较重大的变化,因此,在开始之前,针对于“是否要迁移成 TS”,有过激烈的争论。
当时的主要顾虑是,代码库在 JS 形态下,能多年维护,说明这种模式可行,而现在还有很多别的事情要做,迁移所需要的成本不小,带来的好处却不确定。保守派的观点,源于其认知中,对生产工具重要程度的排序相对偏低。但是从结果来看,生产工具的改进,对整个项目的发展,作用很大。我们待会儿来详细说明。
另外,争论的产生,也由于此类事情,当时不容易有很多定量论据,而主观判断的说服力不足。因此争论过程中,先用 zrender 尝试迁移了 TS,定量地得到了工作量估计、时间估计的经验,以及能够大致判断出 ts 对于我们项目的优劣。这样证明了迁移有可行性的且风险可控。于是,接下来展开了 ECharts 的迁移工作。
我们来看一看,ts 对于 ECharts 带来的好处。
首先,ECharts 有越来越多的社区代码贡献,而非像最初始一样,依靠着几个头脑中知悉代码全部细节维护人。那么,可读性就变得尤其重要。ts 提供了形式化的方法来描述参数、属性的类型,尤其是大量的自定义业务类型。这些描述可被工具检查,可被 IDE 静态分析,于是看代码时,这些信息就不再需要四处发掘,记忆在脑中。
有了静态类型检查后,ECharts 5 对一些代码结构的重构有了质量保证。ECharts 功能庞杂,是个不小的项目了。重构时需要保证逻辑等价,如果没有类型检查,这所带来的心智负担非常大,脑中需要记住的类型信息非常多,出错的概率大大增加。因为 ECharts 功能繁多,有些隐藏的功能和设定,如果修改出了 bug ,因为开源项目的不及时性,得到反馈再修复的周期可能相对比较长。但是类型检查能避免掉不少这类的 bug ,是开源项目质量保证的重要工具。
此外,类型检查也降低了 code review 的心智负担,能更快得阅读代码、走查代码。
最后,开发体验自然会有很大的提升,这是 TS 的本身特点。
ECharts 迁移 TS 的主要工作,是集中一个时间段完成的。如果边迁移边进行其他的开发或重构,则不易保证逻辑的等价性,如果发生问题,很不易查出来。
迁移的具体执行,首先是所有文件都改成 .ts 后缀,并且标注为 ts-nocheck 。然后逐步每个文件加上类型,去掉 ts-nocheck 。
对于 ECharts 的使用者来说,类型的严格程度和正确性比之前更高了。
对于 ECharts 的维护者来说,我们给数百 option 都赋予了类型,从而,这些配置项相关的操作代码,都能得到类型检查,判断是否出现笔误。工具函数、基类等等基础设施的类型,也进行了精心的设计,比较注意使用 泛型重载等等 ts 特性,以便上层有更准确的类型推导。此外,我们也不再需要单独维护 d.ts 文件,开发者所需的 d.ts 直接可以构建产生。
其他
以上就是 ECharts 5 在开发者体验方面的提升,在下一篇文章中,我们会介绍 ECharts 在无障碍访问方面的努力。