技术拆解-动态关系可视化组件
我们做了什么,解决什么问题?
解决业务方必须用命令式调用 ZRender 的问题。
业务方可以通过声明式调用我们的库,给其屏蔽底层 ZRender 的命令式调用,降低业务方成本和心智负担。
这个和 AIGC 组件库本质上是一样的,都是向下封装底层,向上提供声明式配置。
(TODO)这个需要抽象出一套通用的程序设计方案。
库的定位
纯绘图库。
节点的绘制、布局、动画都是业务方计算好的。
环境搭建
1 | |
业务方的难点
节点的绘制,目前是 formatter 的方式
因为内部节点的时间依赖于外部的整体时间,这样一旦某个节点的前置时间变更了,那这个节点就得跟着变更动画时间。
目前已经改为了组件的形式,类似 vue
formatter=>vue 组件
方案设计
原则:数据驱动。
ZRender 已经实现了帧循环调度,我们只需要关注如何将用户配置转为 ZRender 的帧配置即可。
1 | |
文档
docs 下的文档分类做得很好。
文件结构
src 下其实分为了 2 个具有上下级关系的独立的库:
外层库:DynamicRelationGraphs.ts,封装了不同周期数据的动画切换逻辑
底层库:libs 下面,这部分原则上应该独立出去,以第三方包的形式引入
核心代码
重点看这 2 部分即可:
core:机制
helper/animation:将用户配置转为 ZRender 的动画配置
动画操控
libs/relation-graphs/RelationGraph.ts
数据更新
libs/relation-graphs/core/RelationGraph.ts 中的updateDataset(dataset: Data)方法。
动画
猜测是直接用 ZRender 的帧动画切换?
Clip
ZRender 的 Clip 的概念:
1 | |
在 ZRender 中,Clip 类通常用于定义动画剪辑,它是一个封装了动画生命周期和行为的类。根据你提供的代码片段,这个 Clip 类包含以下属性和方法:
_life: 动画剪辑的总寿命,即动画从开始到结束的总时间。_delay: 动画剪辑的延迟时间,即从动画创建到实际开始播放的时间。_inited: 表示动画剪辑是否已经初始化的标志。_startTime: 动画剪辑的开始时间。_pausedTime: 动画剪辑暂停时的时间。_paused: 表示动画剪辑是否处于暂停状态的标志。animation: 动画对象,可能包含具体的动画行为和参数。loop: 布尔值,表示动画是否循环播放。easing: 动画的缓动函数类型,用于控制动画的速度变化。easingFunc: 缓动函数,根据给定的比例返回一个介于 0 到 1 之间的值,用于调整动画的播放速度。next: 指向下一个动画剪辑的引用。prev: 指向前一个动画剪辑的引用,用于形成动画剪辑链。onframe: 每帧动画执行时调用的回调函数。ondestroy: 动画剪辑销毁时调用的回调函数。onrestart: 动画剪辑重新开始时调用的回调函数。constructor(opts: ClipProps): 构造函数,用于创建一个新的Clip实例,opts是一个包含初始化参数的对象。step(globalTime: number, deltaTime: number): 动画剪辑的步骤函数,用于更新动画状态。globalTime是全局时间,deltaTime是自上次调用以来的时间差。pause(): 暂停动画剪辑的方法。resume(): 恢复动画剪辑的方法。setEasing(easing: AnimationEasing): 设置动画剪辑的缓动函数的方法。
这个 Clip 类是 ZRender 动画系统中的一部分,用于控制和组织动画的播放。开发者可以通过创建 Clip 对象并设置相应的属性来定义动画的行为,然后将其添加到 ZRender 的动画队列中进行播放。
组件库的局限性
只适用于纯展示的场景。
如果涉及交互修改数据和状态,就会有问题。比如用户点击后节点颜色变红。因为这涉及修改帧数据了。
问题案例
Rect 中的文字绘制不出来
ZRender5 的 API 有变更:https://github.com/ecomfe/zrender/issues/1074
另外组件库本身有问题,这个拷贝,把 ZRText 对象拷贝成 JSON 了:
1 | |
解决方法有 3 个:
修复组件库
1 | |
扩展绘图功能
修改 Node.ts 的__updateBaseShape方法,根据传入的参数实例化 ZRText 对象,类似这样:
1 | |
通过 customRender 实现
修改初始化 DynamicRelationGraphs 的第三个参数 option,类似这样(注意:这个是伪代码,待验证):
1 | |