如何设计与实现思维导图可视化方案
分享人:泽辉,小米
应用场景
- web版的xmind,支持定制需求。应用于测试用例管理。
- 智能制造工艺流程、资产原型管理、前端能力地图管理、小米笔记思维导图。自定义节点、节点间的连接。
起步面临的问题
- 技术选型繁多
- 有些选型不再迭代
- 可控制集成扩展有限,比如支持DOM自定义、扩展至React/Vue
- 业务组件化诉求高,定制化需求无法开箱即用,二次开发成本高
目标
- 满足丰富的应用场景
- 技术层面定制化程度高。底层可控、算法可控、工作流可控。
技术选型
底层使用D3.js
- 控制粒度精细
- 成熟产品丰富
方案设计
mife-graphic实现方案
1.引擎
- D3.js、Echarts、Antv、mife-graphic.core
2.Component扩展
Component.chart
Component.flow
Component.okr
…
3.Editor/React/Vue上层封装
- Hina-Editor、Sale-Manage…
物料市场
各个组件 -> 不同的组合 -> 不同的功能需要
Graphic API
Constructors
- constructor
Properties
- data
- gLink
- gNode
- gTransform
- gZoom
….
Methods
- resizeUpdate
- setTransform
…
通过继承这一层组件可以开发更多的底层组件。
简单实现
selection-init
1 | export function svgInit(this: Core.Graphic, selection: d3.Selection<any, any, any, any>) { |
selection-event
selection-update
…
实现都比较容易理解,这里不一一例举了。
方案设计核心原则
单一职责原则
- 一个程序只做好一件事
- 如果功能过于复杂就拆分开,每个部分保持独立
开放/封闭原则
- 对扩展开放,对修改封闭
- 增加需求时,扩展新代码,而非修改已有代码
目标达成
Mind脑图
- 布局/编辑/折叠
- 历史记录/复制粘贴
OKR扩展
- React扩展
- 子节点全自动布局
性能和扩展
性能优化粒度可控,达到最小Funtion。
对主流框架扩展性保持良好,未来底层考虑扩展Canvas/WebGL。
数据推荐
《数据可视化(40位数据设计师访谈录)》
如何打造超大规模图可视化画布
分享人:逸达,阿里
渲染优化方案
基于时间切片分批渲染DOM
长任务会卡死浏览器,切割任务分块执行主线程就不会阻塞。所以即使时间慢了,最终图还是会出来,不至于卡死浏览器。
关键API
1 | window.requestIdleCallback(callback); |
该方法会在浏览器空闲期间调用。
基于可视化范围节点裁减渲染
只渲染实际需要渲染的内容所在的画布区域(再加一些缓冲区域),其余被裁减的区域不渲染,这样会大大提高性能。
基于缩放级数的节点分级LOD(Lazyload)处理
只有在用户需要看细节时再渲染细节内容。
基于Canvas渲染节点
基于DOM(或SVG)开发成本较低,但性能问题较大
基于Canvas性能优异,但开发成本较高,且难以实现灵活布局。
Canvas化
通过react-reconciler实现的基于Yoga Layout布局的自定义G Canvas渲染器。可广泛支持底层基于G渲染的AntV系列产品,如G6,G2。
它支持完整的Flexbox布局,及CSS语法子集。提供基础Host组件:Shape、Rect、Text、Image等
既有极高的渲染性能,又有接近于HTML+CSS的开发效率
更多优化
- 服务端预渲染节点
- WebGL渲染器
- WebWorker预计算
推荐资料
- 自己写个React渲染器: 以 Remax 为例(用React写小程序)https://juejin.cn/post/6844903946016784392
- Building a Custom React Rendererhttps://www.youtube.com/watch?v=CGpMlWVcHok
- Figma 技术博客https://www.figma.com/blog/section/engineering/Streaming
- Massive Environments from 0 to 200 MPHhttps://www.gdcvault.com/play/1012335/Streaming-Massive-Environments-from-0
- 设计模式:可复用面向对象软件的基础Erich Gamma(Eclipse, VSCode 负责人)
如何构思和开发开箱即用的图表库 - G2Plot
分享人:新茗,蚂蚁金服
关于G2Plot
G2Plot的诞生与定位
为什么有了G2(常规统计图表可视化引擎),还会有G2Plot呢?
G2使用图形语法绘图,有一定上手成本,非开箱即用。所以需要一个简单、易用且具备一定扩展能力的图表库——G2Plot。
G2Plot有下述优点:
- 开箱即用,默认具备良好视觉和交互体验
- 易于配置,配置化API且使用认知统一
- 开发可扩展,最好是能够直接发挥图形语法的想象空间
定位:基于G2图形语法理论的开箱即用统计图表库。
G2Plot做什么?不做什么?
会做:
- 基于图形语法封装业务图表
- 遵循可视化设计规范进行针对性优化
- 配置式API降低成本
不会做(G2做)
- 图表繁琐的实现细节
- 布局、交互、动画、事件机制
技术架构
核心思路
G2命令式API用配置式API替代
1 | // G2 |
=> 适配器 =>
1 | import { Line } from '@antv/g2plot'; |
适配器设计
适配器如何一图一做,每增加一种新图表,就需要增加一份绘图逻辑(扩展成本)。一旦需求发出变化或者底层依赖API变化,就很难维护了。
流水线组合的适配器
1 | // 折线图适配器 |
这里借助了lodash的flow函数思想,按顺序调用数组中的方法,每个函数执行的结果作为下个函数的入参。
每个图表的适配器可以拆分为若干个适配器,每个适配器执行之后,还是新的适配器。可以进行自由的组合,前置依赖关系可以通过顺序保证,彼此之间没有很耦合的依赖。
适配器进行流水线化之后,可以将原来混杂的绘图逻辑清晰地划分为若干步骤。
模块内聚,减少耦合,提高复用性。
那么模块是如何拆分的呢?
模块划分
图表基本功能:几何图形+坐标轴+图例+悬浮信息+数据标签+图形标注等。
图表增强功能:交互、动画、状态、主题等。、
内置的适配器模块划分和图表的功能基本是一致的
复用性
有了适配器以后,如果绘制折线图,替换为line geometry适配器,柱状图替换为interval geometry适配器。其余适配器,比如axis、legend不用改变。
维护性
降低复杂性的基本方法,就是把复杂性隔离。”如果能把复杂性隔离在一个模块,不与其他模块互动,就达到了消除复杂性的目的。“
软件架构的复杂度:
- 认知负荷
- 协同成本
G2Plot考虑了这两点
- 逻辑符合思维习惯,与物理世界的概念符合。如:G2Plot按照图表组成和功能进行模块划分。
- 模块相对独立,边界清晰,通过原子化的方式进行组合。由于架构的约束,G2Plot 开发者的改动只会影响自己的那部分模块,边界较为清晰,代码也更容易维护,且每个模块有对应的单元测试。
扩展性
支持定义适配器
API设计思考
schema 结构设计
认知统一
- 不同图表同一类型的配置命名相同
- G2、G2Plot 相同概念保持一致的配置
- 贴合适配器模块
配置简单
- G2 提供的灵活性与使用成本的权衡
- G2Plot 进行一定的封装,提供更简单的配置化方式
BI / low-code 友好
- 面向 BI 低代码搭建的友好
如何选型 G2、G2Plot、AntD-Charts
react 技术栈且图表自定义诉求不强:AntD-Charts
定制诉求不强,G2Plot 内置图表基本可满足:G2Plot
具备丰富交互、需要定制的个性化信息图表:G2Plot自定义扩展图表adaptor模式 或者 G2 / G
从 G、G2、G2Plot 再到 Ant Design Charts,我们只有一个目的:降低开发入⻔⻔槛,如何选择取决于你对各图表库的理解程度。