scale 的范围关系到图形最终的绘制范围。通过不同字段的 scale 同步,可以达成数据对齐、图形对齐的操作。

问题

技术前提:

  • 同一个 view 中,使用的数据源是同一个。
  • 不同 view 使用不同的数据源(当然也可以使用同一个数据源)

那么 scale 同步主要解决问题:

  1. 同一个 view 中,数据源中不同字段之间的同步
  2. 不同 view 中,数据源中的字段进行同步
  3. 连续字段、分类字段均可以进行 scale 同步

额外的问题:

  1. API 的易用性问题,可以方便在 view 层一键设置 view 中的所有一些字段同步。
  1. chart.scale('field', {
  2. sync: 'sync-field',
  3. });

在 chart 上,给 chart 中所有的 field 字段设置为同步。

  1. scale 配置的同步和覆盖

即时是同步的字段,也需要有自己不同的配置,比如 alias。

方案

核心逻辑是,sync 名字指向相同的 scale 进行自动同步。

  • view 增加 id 属性,每个 view 具备不同的 id。
  • scale 配置通过冒泡向上传递合并,最终到顶层 view 中(最小距离优先原则)。
  • scale 的创建和缓存均在最顶层的 view 中 Record,缓存的 key 为 view.id + field。
  • scaleDef 增加 sync 字段,在生成过程中维护一个 Record 的关系,最后对于 sync 相同的scale 数组进行同步。

使用示例

image.png

这个图可以概括所有的 scale 同步问题了。

  1. 同 view 的不同字段进行同步
  1. view1.scale('y1', {
  2. sync: 'y',
  3. });
  4. view1.scale('y2', {
  5. sync: 'y',
  6. });

将 y1、y2 的 ref 默认指向到同一个字段。

  1. 不同 view 的不用字段
  1. view1.scale('y1', {
  2. sync: 'y1',
  3. });
  4. view2.scale('y3', {
  5. sync: 'y1',
  6. });

将 y1,y3 字段 sync 名字 指定到同一个字段上。

  1. 不同 view 的相同字段
  1. chart.scale('y1', {
  2. sync: 'y1'
  3. });

自动将 chart 中所有 y1 字段的 scale sync 到同一个名字。

  1. 取消同步

**

  1. chart.scale('y1', {
  2. sync: false,
  3. });

sync = false / undefined / null 自动将 sync name 设置成 view.id + field 的形式

实现

见代码 PR。主要是:

  1. scale-pool:缓存和管理 scales,以及需要同步的 sync 数据结构。挂载在 view 上,但是实际上只有顶层 view 才会有用
  2. scale-pool API
    1. createScale(包含 cache 和更新 cache)
    2. sync 同步 scales
    3. clear
  3. view 中
    1. 创建过程 scaleDef 冒泡到最顶层逐步合并
    2. 创建、获取、同步 scale 方法变成递归 view 到 root 进行处理
    3. geometry.scales 增加方法获取这个 Geometry 需要的所有 scale map

scale 的创建和更新逻辑全部在 scale-pool 中,view 层只管递归的 rootView,然后组织 scale 先关的流程。