type
Post
status
Published
date
Feb 7, 2020
slug
summary
浅入浅出 echarts 图表库实现原理
tags
Web dev
category
技术分享
icon
password

您将收获

  • 浅入浅出 echarts 图表库实现原理
  • 更加熟悉 echarts 配置项

echarts

最早(2012.8)由百度工程师开发做内部报表用,2013.6 开源,中间版本迭代,2018.1 捐给 Apache 开源基金会(ASF)开始孵化。
成为 Apache 孵化项目的意义:
  1. 对用户(开发中)来说使用更放心,由一家公司背书变为由 Apache 背书,不怕公司出现问题(公司倒闭、核心开发者离职 or 裁员、突然不开源了),反例 element-ui
  1. 对 committer 来说,不会觉得我是在免费给这个公司贡献代码,除非你想去那个公司
  1. 对项目来说,在开源社区得到更多的关注,吸引更多优秀的 committer 为项目舔砖加瓦

echarts 架构

notion image
Image
要理解这个架构,我们还需从底层看起,如果不使用库,我们怎么绘制图表。以一个饼图为例
notion image
  1. 使用 canvas [代码]
  1. 使用 svg
    1. notion image

zrender 的职责

  • 渲染引擎的隔离(Canvas / SVG / VML / …) VML
  • 图形元素的抽象 & 状态维护(Element / Group / Layer / …)[代码]
    • notion image
  • 用户交互的封装(mouse event / touch / gesture / drag / …)
  • 动画(frame 管理 / easing / …)
  • 图形的坐标系变换(transform)、包含判断、曲线 …
  • 其他基本工具(eventful / color / array diff / SVG path converter / …)

echarts-系列(series)、组件(components)和坐标系(coordinateSystem)

zrender 是对图形绘制的抽象封装,echarts 则是对图表的抽象与封装,其中最重要的是这几个概念
  • 系列 series 即图表类型(line / pie / bar / scatter / tree / graph / map / treeMap…) 一个图里会有多个系列
    • notion image
  • 组件 components 除了系列,都是组件,如坐标轴、坐标系底板、操作用的控件等
    • notion image
  • 坐标系 coordinateSystem 系列的一部分,由组件构成(笛卡尔坐标系、极坐标系、日历、地理坐标系、地图服务)
    • 不同的坐标系所需组件不同,如:笛卡尔坐标系需要 xAxis、yAxis 组件;极坐标系则需要 angleAxis、radiusAxis 组件。
      相同数据在不同坐标系的展示: https://www.echartsjs.com/examples/zh/editor.html?c=scatter-polar-punchCard https://www.echartsjs.com/examples/zh/editor.html?c=scatter-punchCard
      [代码]

echarts-工作流(pipeline)

饼图为例
notion image
Image
动画的实现?
hasAnimation ? // animateTo will stop revious animation like update transition el .animate() .when(200, { position: position, }) .start('bounceOut') : el.attr('position', position);

echarts-性能优化

什么时候存在性能问题

数据越多性能越差。就像 antd Select 组件有 1000 个选项时会明显卡顿一样,虽然 canvas 渲染比 dom 渲染快些
我没有经过精确的测试,用一个例子来大致感受下:
  • 1000 个数据点 无 视觉上的卡顿,performance 观察存在 146ms 卡顿(> 1000ms/60)
  • 10000 个数据点 有 视觉上的卡顿,performance 观察存在 354ms 卡顿
  • 100000 个数据点 有 视觉上的卡顿,performance 观察存在 509ms 卡顿
从前端渲染角度如何定义大数据,数据点大于像素点,如:1920 * 1080 = 2,073,600
我之前遇到的卡顿问题:
  1. 2880 个数据点,1 个图 performance 观察存在 700ms 卡顿(???)
  1. 一个图渲染完不能直接展示,要等四个图都渲染完才展示,4 个图就卡 3 秒,这部分感觉和 react 也有关系

echarts 里如何解决

echarts 在性能方面的设计感觉一般:
  1. 不同的 series 有不同的配置,可以在配置项中搜索 sampling(采样)、progressive(渐进式渲染)…
  1. 视觉上的过渡,可以在配置项中搜索 animation、showLoading…
  1. 高阶一点用 echartsInstance. appendData,把数据切片,这部分由开发者控制,工作量大,数据切成多大一片不好说:切大了,渲染一块数据还是卡;切小了,整个渲染完成时间会不会更长(虽然中间是有动画的),另外和 react 结合是否会存在其他问题

其他图表库浅谈

D3
echarts
G2
bizcharts/viser-react
https://observablehq.com/@d3/pie-chart?collection=@d3/d3-shape
-
https://g2.antv.vision/zh/examples/gallery/pie
https://bizcharts.net/products/bizCharts/demo/detail?id=pie-labelline&selectedKey=%E9%A5%BC%E5%9B%BE
命令式链式调用
声明式配置传递
命令式链式调用
声明式 jsx
-
-
-
-

关于 g2

@antv/g2 - 折线、柱状、饼状 @antv/g6 - 树、图
bizcharts = @antv/g2 + react viser-react = viser(基于 @antv/g2)+ react viser-graph-react = viser-graph(基于 @antv/g6) + react
g2 架构 https://g2.antv.vision/zh/docs/manual/concepts/history
个人理解 g2 对标 D3。

g2 与 echarts 对比

  • 优点:
      1. 布局做的好,legend 与图表内容不遮挡、label 不遮挡 https://zhuanlan.zhihu.com/p/109532433
  • 缺点:
      1. 直接使用 g2 是极好的,只要习惯了 d3 风格的链式调用,但要在 React 中使用存在一些问题:
    • 学习成本:bizcharts/viser-react 用 jsx 封装 g2,要学两套 API
    • 功能缺陷:bizcharts/viser-react 没有完整实现 g2 的交互

DataSet

echarts、g2 都有这个功能,用来做数据预处理,就使用体验来说,g2 的 DateSet 体验不错

感想

  • 优秀的 UI system 有很多共通的地方:
  1. 底层操作是命令式(dom 操作、canvas、webGL);
  1. 封装时大多会遵循的原则: MV**、 单向数据流、自定义事件 eventEmitter
  • 数据可视化技术上还可以探索的:
  1. 3D 图表
  1. 风格化渲染,手绘风:https://github.com/timqian/chart.xkcd
  • 数据可视化还有值得学习的是产品层面的:
  1. 具体场景下,什么类型的图表更适合表现数据
  1. 一些不常见的类型的图表是干什么的
React HooksUnity 小结(一)- JavaScript 与 C#