前言:因为最近公司业务需求,需要在App中实现关系拓扑图。由于自己之前学习了下Vue.js和一些前端知识和ThinkPHP。就自告奋勇把任务接下来了。后来才发现真的是too young too simple,后端数据接口和Android部分都还好说,但这个拓扑图真是让我欲哭无泪,后来了解了Vis.js和百度出品的echart,也都尝试着去实现自己想要的功能。却都因为可定制化差强人意,不能满足我的强迫症而放弃。这时,我的目光落在了d3.js上。比起上面两个框架,虽然d3.js可定制化能力强,但这也意味着学习成本更高,实现难度更大。而最巧的是d3.js从v3版本升级到了v4版本,其中的接口都发生了很大的变化,网上的相关的资料并不多,而且官方文档又是英文比较“简洁”。对新手来说真的十分不友好,我只好看着文档和网上仅有的资料不断抹着眼泪,不断尝试。自己接的任务,跪着也要写完。
以下是核心代码:
主要分为三块:html代码和js代码、css代码,这里css用的预编译器是stylus
<template>
<div id="app" class="container">
<button type="button" class="exit" @click="jsBack" ref="exit" v-if="isPc">退出</button>
</div>
</template>
<script type="text/ecmascript-6">
// import vis from 'vis'
import * as d3 from 'd3'
export default {
name: 'app',
data () {
return {
relation: {},
cname: '',
isPc: false
}
},
methods: {
jsBack () {
// 返回按钮
var u = navigator.userAgent
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1
var isiOS = u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端
if (isAndroid) {
// Android端
window.android.back()
} else if (isiOS) {
// ios端
}
},
showd3 () {
// 获取body高度和宽度
let height = document.body.clientHeight
let width = document.body.clientWidth
//移动端设备横竖屏重新加载页面
function change () {
window.location.reload()
}
window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', change, false)
// 节点大小(圆圈大小)
const nodeSize = 35
// 初始化时连接线的距离长度
const linkDistance = 130
// 赋值数据集
var nodes = this.relation.nodes
var links = this.relation.links
// 设置画布,获取id为app的对象,添加svg,这里的图像用了svg,意为可缩放矢量图形,它与其他图片格式相比较,svg更加小,因为是矢量图,放大不会失帧。具体可以自行百度svg相关知识
var svg = d3.select('#app').append('svg')
.attr('xmlns', 'http://www.w3.org/2000/svg')
.attr('version', '2.0')
.attr('class', 'svg')//给svg设置了一个class样式,主要作用是长宽设置为100%
// 设置力布局,使用d3 v4版本的力导向布局
var force = d3.forceSimulation()
.force('center', d3.forceCenter(width / 2, height / 2))//设置力导向布局的中心点,创建一个力中心,设置为画布长宽的一半,所以拓扑图会在画布的中心点
.force('charce', d3.forceManyBody().strength(-70))//节点间的作用力,如果不设置.strength(-60)的话,默认是-30
.force('collide', d3.forceCollide())//使用默认的半径创建一个碰撞作用力。radius默认所有的节点都为1
// 设置缩放
// svg下嵌套g标签,缩放都在g标签上进行
var g = svg.append('g')
// d3.zoom是设置缩放,pc端是滚轮进行缩放,在移动端可以通过两指进行缩放
var zoomObj = d3.zoom()
.scaleExtent([0.5, 1.2]) // 设置缩放范围
.on('zoom', () => {
//监听zoom事件,zoom发生时,调用该方法
const transform = d3.event.transform //获取缩放和偏移的数据,不懂得同学可以自行通过console.log(d3.event.transform)滑动滚轮查看数据变化
g.attr('transform', transform) // 设置缩放和偏移量 transform对象自带toString()方法
})
.on('end', () => {
// 该方法在缩放时间结束后回调
// code
})
svg.call(zoomObj)
// 绘制箭头
//箭头
// eslint-disable-next-line no-unused-vars
var markerBlue =
g.append('marker')
.attr('id', 'resolvedBlue')
//.attr("markerUnits","strokeWidth")//设置为strokeWidth箭头