scale 的范围关系到图形最终的绘制范围。通过不同字段的 scale 同步,可以达成数据对齐、图形对齐的操作。
问题
技术前提:
- 同一个 view 中,使用的数据源是同一个。
- 不同 view 使用不同的数据源(当然也可以使用同一个数据源)
那么 scale 同步主要解决问题:
- 同一个 view 中,数据源中不同字段之间的同步
- 不同 view 中,数据源中的字段进行同步
- 连续字段、分类字段均可以进行 scale 同步
额外的问题:
- API 的易用性问题,可以方便在 view 层一键设置 view 中的所有一些字段同步。
chart.scale('field', {
sync: 'sync-field',
});
在 chart 上,给 chart 中所有的 field 字段设置为同步。
- scale 配置的同步和覆盖
即时是同步的字段,也需要有自己不同的配置,比如 alias。
方案
核心逻辑是,sync 名字指向相同的 scale 进行自动同步。
- view 增加 id 属性,每个 view 具备不同的 id。
- scale 配置通过冒泡向上传递合并,最终到顶层 view 中(最小距离优先原则)。
- scale 的创建和缓存均在最顶层的 view 中 Record
,缓存的 key 为 view.id + field。 - scaleDef 增加 sync 字段,在生成过程中维护一个 Record
的关系,最后对于 sync 相同的scale 数组进行同步。
使用示例
这个图可以概括所有的 scale 同步问题了。
- 同 view 的不同字段进行同步
view1.scale('y1', {
sync: 'y',
});
view1.scale('y2', {
sync: 'y',
});
将 y1、y2 的 ref 默认指向到同一个字段。
- 不同 view 的不用字段
view1.scale('y1', {
sync: 'y1',
});
view2.scale('y3', {
sync: 'y1',
});
将 y1,y3 字段 sync 名字 指定到同一个字段上。
- 不同 view 的相同字段
chart.scale('y1', {
sync: 'y1'
});
自动将 chart 中所有 y1 字段的 scale sync 到同一个名字。
- 取消同步
**
chart.scale('y1', {
sync: false,
});
sync = false / undefined / null 自动将 sync name 设置成 view.id + field 的形式
实现
见代码 PR。主要是:
- scale-pool:缓存和管理 scales,以及需要同步的 sync 数据结构。挂载在 view 上,但是实际上只有顶层 view 才会有用
- scale-pool API
- createScale(包含 cache 和更新 cache)
- sync 同步 scales
- clear
- view 中
- 创建过程 scaleDef 冒泡到最顶层逐步合并
- 创建、获取、同步 scale 方法变成递归 view 到 root 进行处理
- geometry.scales 增加方法获取这个 Geometry 需要的所有 scale map
scale 的创建和更新逻辑全部在 scale-pool 中,view 层只管递归的 rootView,然后组织 scale 先关的流程。