为力导向图添加缩放移动特性
孙泽辉

在没有Echarts 之前,D3是图表项目的最佳选择,而有了Echarts,以及AntV之后,D3在图表领域就渐渐的失去了优势。貌似没看见有力导向图的轮子可用,d3开搞!

过程👉

d3仓库:d3/d3: Bring data to life with SVG, Canvas and HTML. (github.com)

从头开始未免太慢了,我找到了一个vue封装一层的组件,打开示例各项参数都挺符合我的要求,不过有一点就是不能鼠标缩放,这样看不到的地方就永远看不见了,这点难道作者没有考虑到吗,疑惑。

image

为了添加自己的逻辑,找到组件位置src/vue-d3-network.vue

引入需要的工具包📦

1
2
3
4
5
6
// 选中svg标签用
import { select } from "d3-selection";
// 放缩画布
import * as zoom from "d3-zoom";
// 合并到d3上
const d3 = Object.assign({}, forceSimulation, { select }, zoom);

以前还说requirejs不能tree shaking,用这种写法直接都不用考虑打包工具了,天生tree shaking,哈哈哈。

为了能整体缩放,添加容器包裹住所有节点和边:

1
2
3
4
5
6
<svg class="net-svg">
<g class="ground">
<g class="node"></g>
<g class="link"></g>
</g>
</svg>

将就看吧,不支持PUG模板标签。。

methods中,找到resize时执行的animate方法,在下面添加自己的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// vue.methods...
animate() {
// simulation restart...
const vm = this;
function zoomed({ transform }) {
// 缩放后记录当前缩放等级
vm.transform = transform;
// 缩放的是容器
d3.select(".ground").attr("transform", transform);
}
// 选中svg标签,添加zoom事件
d3.select(".net-svg").call(
d3.zoom()
.extent([
[0, 0],
[this.size.w, this.size.h],
])
.scaleExtent([1, 8])
.on("zoom", zoomed)
);
},

放大后效果(图片5M,耐心等待☕):

image

这时已经可以缩放了,但是鼠标点击节点和标签时还有偏移,需要将transform加回来。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 鼠标拖动节点事件处理方法
move(event) {
if (!this.dragging) return;
let pos = this.clientPos(event);
if (this.nodes[this.dragging]) {
this.simulation.restart();
this.simulation.alpha(0.5);
// 将现在缩放等级加回来
const _trans = this.transform;
this.nodes[this.dragging].fx = (pos.x - _trans.x) / _trans.k;
this.nodes[this.dragging].fy = (pos.y - _trans.y) / _trans.k;
}
},

关于缩放后的坐标计算😋:

image

由点放大倍后的点有如下关系:

如,点等比放大2倍后应为,即点乘以缩放矩阵

image

但是由于我们屏幕大小固定,又因为d3给算出来了转换后的坐标偏移,直接对其求逆矩阵就好了

image

所以就有了上面的代码:

1
2
this.nodes[this.dragging].fx = (pos.x - _trans.x) / _trans.k;
this.nodes[this.dragging].fy = (pos.y - _trans.y) / _trans.k;
  • pos 鼠标距离视口坐标
  • _trans.x,y 转换后的原点坐标
  • _trans.k 缩放等级

上面就是全部的对源码的操作了,还有些细节我没贴,就这样吧。。

总结🙌

d3 真好用,好就好在7个版本7个写法😅

我fork出来的项目地址:

sunzehui/vue-d3-network: Vue component to graph networks using d3-force (github.com)

原仓库地址:

emiliorizzo/vue-d3-network: Vue component to graph networks using d3-force (github.com)

参考资料:

javascript - Get mouse position in SVG co-ordinates after zoom - Stack Overflow

(92条消息) 【OpenCV & Python】图像几何变换:旋转,缩放,平移_DXduxing1的博客-CSDN博客_python图像几何变换

(92条消息) 计算机图形学(四)几何变换_3_矩阵逆变换_heyuchang666的博客-CSDN博客_平移矩阵的逆

[機器視覺技術 - 陳兵旗 - Google 图书](

 Comments
Comment plugin failed to load
Loading comment plugin
Powered by Hexo & Theme Keep
This site is deployed on
Total words 89.4k