用D3.js实现一个图形的套路

现在接到一个可视化的图形需求,我会比较慌,思考了下,是因为我在具体实现上,还没形成自己的编码套路,导致无法快速对图形进行技术上的拆解。

因此我准备根据这次的财富指南针项目,从同事的编码中,整理下编码套路,作为今后其他需求的指引。

需求确认方面的内容,这里就不赘述了,本文只考虑技术实现上的思路。

其实只要我们将数据操作、视图渲染、事件完全分离开,就已经是很不错的设计了。

牢记前端是数据驱动的领域。

【数据驱动】理念

这是每时每刻都要牢记于心的准则。这关系到了你的程序设计思路,是核心中的核心。

我们遵循这个理念,只需要将整个组件拆分为若干个独立的小组件,然后给小组件设计事件、交互、样式、数据等接口,后面数据变更后,驱动这些接口即可。

如何应用D3的每个功能

平时多翻翻Observable的案例,上面有非常多的示例可以参考,见识得多了,你就知道哪些能实现、该如何实现了。

1、先找到对应功能的github代码库,查看文档

D3将每个功能都拆分为独立的代码库了,首页是这里:https://github.com/d3

比如缩放就是d3-zoom:https://github.com/d3/d3-zoom

2、阅读一遍文档

3、查看Observable上面的案例代码

比如d3-zoom的:https://observablehq.com/collection/@d3/d3-zoom

数据结构

可视化是数据驱动的,这个永远要牢记。

确认好数据,并预定好数据结构数据特性,会让你后面少很多麻烦。

另外,一般项目初期都没有真实数据,因此我们得自己生成假数据。

产出:数据结构说明文档、假数据生成函数

配置项

配置项主要是样式、接口相关的内容定义。

这个要和具体使用我们图形的业务方开发沟通好,类似前后端开发的接口协定。

产出:一个包含注释、默认值的JavaScript对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//配置信息
let config = {
//图表内补白
padding: 20,

//默认分 25 层
arcLayerLength: 25,

//弧形圆角像素值
cornerRadius: 2,

//是否开启动画
animation: true,

//开始弧形动画过渡时间,开始动画时生效
duration: 750
}

组件拆解

这一步是放在最前面的,就是将整个图形拆解为所使用技术内置的组件。

比如我们使用D3,那么就将整个图拆解为D3的tooltip、比例尺、path等等。

可以从大到小,将g以及g里面包含的元素都确定下来。

这一步确定好,基本就可以确定程序的结构了。

产出:一个标记好的解构图、D3各组件的实例(具体样式细节后面再调)

比如这样的:

compass

事件/交互/动效定义

把需要交互的内容所涉及的事件确定下来。

这个会影响页面元素的移动和外观变更。

常见的内容包括:高亮、点击、鼠标悬浮等等。

常量/变量定义

这个其实和配置可能有一些关联性和重合度,视具体情况而定。

最终的程序结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 数据对象
let data = []

// 常量定义
const SOME_CONST_VARIABLE = 123

// 生成假数据
function makeFakeData()
{
// TODO
}
data = makeFakeData()

// 配置项
let config = {
// TODO
}

// 比例尺

// tooltip

// 弧形

// 线条

// text

// 交互事件相关的功能函数

注意事项

数据处理耗费时间巨大,一定要先把逻辑理清楚,并预留足够的时间。

旋转transform要用熟练,要把常用的几个d3/JavaScript的数学函数完全理清楚,比如Math.cos()、Math.sin()等等,特别是针对环形图,用到数学计算比较多。