版本:V5.3.3
背景
ECharts
作为一个配置的图表引擎,同时默认的渲染器又是Canvas
。如果想要对ECharts
的某个图元做一些自定义的编辑,如果ECharts
并有没开发配置项、或者配置项的粒度不够,这时候就会变的比较困难。本文尝试探寻有没有方式可以拾取ECharts
的图元,拾取之后是否有一定的方式可以针对图元做特定的编辑。
方案
术语速查手册方案分析
一种走不通的方案,这里简单做下解惑,以免产生【官网是如何实现的】这种疑问。
简单查了下源码cheat-sheet.js — apache/echarts-www — GitHub1s,发现官网实例的实现方式为:
- 绘制静态图表
- 人工分析图元,区域、名称、配置项。
- 创建对应的
Graphic
(Rect) - 给
Graphic
添加必要的事件(覆盖:填充颜色,点击:渲染配置项类型) - 基于
ECharts
渲染Graphic
结论
由于方案本质为人工分析的静态图表,即不具备推广价值。
基于SVG渲染器-自定义标签
既然基于Canvas
图元拾取相对困难且ECharts
支持SVG
渲染器,接下来尝试基于SVG
Dom元素去做图元拾取。
ECharts SVG Dom 分析
从SVGRender中已知,ECharts
为了使指令转译层尽量单薄仅抽象了三个svg
标签即path
,tspan
,image
。绝大多数元素都使用path来渲染。
通过探查渲染结果发现SVG Dom
中未包含任何与配置项相关的属性信息,由于无法判断path
标签究竟是通过哪个配置项来生成的,这就给图元拾取造成了一定的困扰。
既然ECharts
渲染的SVG
Dom
未包含配置项相关的属性信息,接下来尝试对ECharts
Pipeline
进行代码侵入,尝试在构建和渲染过程中使最终结果包含配置项信息。
ECharts 待渲染元素属性分析
通过对ECharts
待渲染元素属性进行分析,发现只有最顶层元素包含__ecComponentInfo
属性。底层元素仍不可知。
结论
通过对ECharts渲染流程做代码侵入,以获取Dom
元素通过哪个配置项得来的方式存在理论可行性,但由于ECharts
【待渲染元素属性】只有最顶层元素包含配置项信息,所以仅侵入渲染器代码并不能很准确的识别到图元信息。若想扩充【待渲染元素属性】使其底层元素同样包含配置项信息则需要对整个渲染流程做代码侵入,侵入规模将不可控。
基于ECharts事件系统的扩充
ECharts
内部本身包含一套事件系统,提供了series
的 click
,dbclick
等事件。本方案尝试对ECharts
的事件系统进行扩充以支持所有元素的回调,并且在回调中抛出具体的图元信息。
ECharts 事件系统分析
ECharts
首先构建了一个handerProxy
事件代理器将Dom
的事件代理至ECharts
内部的元素。当对应的事件触发是会通过findHover
来获取触发事件的元素,如果元素为非静默模式(SILENT
)将会在该元素上对事件进行向上冒泡,最终冒泡至ECharts
对象。ECharts
对象会根据触发事件的对象来获取ECharts Data
,如果触发事件的对象确定包含ECharts Data
则会在最外层的Dom
上抛出所对应的事件。至此完成整个事件冒泡。
ECharts事件对象分析
结论
殊途同归,ECharts
事件对象仍是ECharts
【待渲染元素属性】。事件对象里不包含图元信息通过改造事件系统同样做不到元素拾取。
扩充 ECharts【待渲染元素属性】
本节尝试调研对ECharts
Axis
模块进行扩充使其包含 __ecComponentInfo
属性,对 Axis
模块的侵入规模以及成本。
新增__ecComponentInfo
属性
以Axis name
为例。
有个技巧,可以搜索.add
方法。add
方法就是将图源添加进Group
的动作。在添加之前必然可以获取被添加的图元。人工分析该图元对应的配置项属性,添加__ecComponentInfo
属性以描述其配置项属性即可。
改动量
ECharts新增__ecComponentInfo
属性
Axis
模块涉及五个文件,14处改动。
.d.ts
根据提示修改即可。
具体过程略。整体规模与新增__ecComponentInfo
属性所改动的文件大致相同。
ZRenderSVG渲染器
一个非常粗糙的示例具体内容待商榷
新增添加图元信息到SVG
属性的方法
1 | function setElInforIntoAttrs(el,attrs){ |
在渲染过程中调用setElInforIntoAttrs
方法
1 | export function brushSVGPath(el, scope) { |
测试用例
略
结论
对信息的注入不可避免
结论
针对图元拾取:
可行,但对信息的注入不可避免,改动规模较大,对ECharts
代码进行二次侵入的方式不可行。需ECharts
团队配合确定新增属性的字段,提交PR
并合入ECharts
代码。
针对图元修改:
基于回调的方式,触发mouseOver
事件或者click
事件后重新setOption
的方式修改样式难度过大,且可能存在性能问题。这部分会基于SVG
渲染器,交由Dom操作来修改。