基于vue2.x+antvx6实现可拖拽编辑拓流程拓扑图
最近公司要求做⼀个拓扑流程图,在⽹上搜寻了⼀些可⾏性⽅案之后,发现好⼀点的可视化拓扑图都是要收费的,于是决定⾃⼰在阿⾥的antv x6基础上做出⼀款简单的产品,以便于后期进⾏修改和操作
项⽬主要版本号:
vue版本:2.x,
antv:@antv/x6": "^1.17.3", "@antv/x6-vue-shape": "^1.2.0",
css预编译器: "less": "^3.10.3",
ui框架:iview ,"view-design": "^4.1.1",
项⽬主要贴图gif:
贴上部分代码:
<template>
<div class="container_warp">
<div id="containerChart"></div>
<RightDrawer class="right_drawer" :drawerType="type" :selectCell="selectCell" :graph="graph" :grid="grid" @deleteNode="deleteNode"></RightDrawer>
<div class="operating">
<div class="btn-group">
<div class="btn" title="圆形节点" @mousedown="startDrag('Circle',$event)">
<i class="iconfont icon-circle"></i>
</div>
<div class="btn" title="正⽅形节点" @mousedown="startDrag('Rect',$event)">
<i class="iconfont icon-square"></i>
</div>
<div class="btn" title="条件节点">
<i class="iconfont icon-square rotate-square" @mousedown="startDrag('polygon',$event)"></i>
</div>
<div class="btn-group_tips" v-if="showTips">
拖拽⽣成</br>资产拓扑图形
</div>
</div>
<div class="btn-group">
<Tooltip content="直线箭头" placement="bottom">
<div :class=" ['btn',currentArrow === 1?'currentArrow':'']" @click="changeEdgeType('normal')">
<i class="iconfont icon-ai28"></i>
</div>
</Tooltip>
<Tooltip content="曲线箭头" placement="bottom">
<div :class=" ['btn',currentArrow === 2?'currentArrow':'']" @click="changeEdgeType('smooth')">
<i class="iconfont icon-Down-Right"></i>
</div>
</Tooltip>
<Tooltip content="直⾓箭头" placement="bottom">
<div :class=" ['btn',currentArrow === 3?'currentArrow':'']" @click="changeEdgeType()">
<i class="iconfont icon-jiantou"></i>
</div>
</Tooltip>
</div>
<div class="btn-group">
<Tooltip content="删除" placement="bottom">
<div class="btn" @click="deleteNode()" >
<i class="iconfont icon-shanchu"></i>
</div>
</Tooltip>
<Tooltip content="保存PNG" placement="bottom">
<div class="btn" @click="saveToPNG()" title="保存">
<i class="iconfont icon-baocun"></i>
</div>
</Tooltip>
</div>
</div>
</div>
</template>
<script>
import '@antv/x6-vue-shape'
import { Graph,Shape,Addon,FunctionExt,DataUri} from '@antv/x6';
import RightDrawer from './components/RightDrawer';
import insertCss from 'insert-css';
import {startDragToGraph} from './Graph/methods.js'
const data = {};
export default {
data() {
return {
graph:'',
value1: true,
type:'grid',
selectCell:'',
connectEdgeType:{ //连线⽅式
connector: 'normal',
router: {
name: ''
}
},
showTips:false,
currentArrow:1,
grid:{ // ⽹格设置
size: 20, // ⽹格⼤⼩ 10px
visible: true, // 渲染⽹格背景
type: 'mesh',
args: {
color: '#D0D0D0',
thickness: 1, // ⽹格线宽度/⽹格点⼤⼩
factor: 10,
},
}
}
},
components:{
RightDrawer
},
methods: {
initX6(){
var _that = this
container: ElementById('containerChart'), width: 1700,
height: '100%',
grid: _id,
resizing: { //调整节点宽⾼
enabled: true,
orthogonal:false,
},
selecting: true, //可选
snapline: true,
interacting: {
edgeLabelMovable: true
},
connecting: { // 节点连接
vuejs流程图插件anchor: 'center',
connectionPoint: 'anchor',
allowBlank: false,
snap: true,
createEdge () {
return new Shape.Edge({
attrs: {
line: {
stroke: '#1890ff',
strokeWidth: 1,
targetMarker: {
name: 'classic',
size: 8
},
strokeDasharray: 0, //虚线
style: {
animation: 'ant-line 30s infinite linear',
},
},
},
label: {
text:''
},
connector: _tor,
router: {
name: _uter.name || '' },
zIndex: 0
})
},
},
highlighting: {
magnetAvailable: {
name: 'stroke',
args: {
padding: 4,
attrs: {
strokeWidth: 4,
stroke: '#6a6c8a'
}
}
}
},
});
insertCss(`
@keyframes ant-line {
to {
stroke-dashoffset: -1000
}
}
`)
// ⿏标移⼊移出节点
<('node:mouseenter',FunctionExt.debounce(() => {
const container = ElementById('containerChart') const ports = container.querySelectorAll(
'.x6-port-body'
)
this.showPorts(ports, true)
}),
500
)
<('node:mouseleave', () => {
const container = ElementById('containerChart') const ports = container.querySelectorAll(
'.x6-port-body'
)
this.showPorts(ports, false)
})
<('blank:click', () => {
})
<('cell:click', ({ cell }) => {
})
<('selection:changed', (args) => {
args.added.forEach(cell => {
this.selectCell = cell
if(cell.isEdge()){
cell.isEdge() && cell.attr('line/strokeDasharray', 5) //虚线蚂蚁线 cell.addTools([
{
name: 'vertices',
args: {
padding: 4,
attrs: {
strokeWidth: 0.1,
stroke: '#2d8cf0',
fill: '#ffffff',
}
},
},
])
}
})
cell.isEdge() && cell.attr('line/strokeDasharray', 0) //正常线
})
})
},
showPorts (ports, show) {
for (let i = 0, len = ports.length; i < len; i = i + 1) {
ports[i].style.visibility = show ? 'visible' : 'hidden'
}
},
// 拖拽⽣成正⽅形或者圆形
startDrag(type,e){
aph,type,e)
},
// 删除节点
deleteNode(){
const cell = SelectedCells()
},
// 保存png
saveToPNG(){
this.$nextTick(()=>{
// 下载
DataUri.downloadDataUri(dataUri, '资产拓扑图.png')
},{
backgroundColor: 'white',
padding: {
top: 50,
right: 50,
bottom: 50,
left: 50
},
quality: 1,
copyStyles:false
})
})
},
// 改变边形状
changeEdgeType(e){
if(e === 'normal'){
connector: 'normal',
router: {name: ''}
}
this.currentArrow = 1
}else if (e === 'smooth'){
connector: 'smooth',
router: {name: ''}
}
this.currentArrow = 2
}else{
connector: 'normal',
router: {name: 'manhattan'}
}
this.currentArrow = 3
}
}
},
mounted(){
this.initX6()
setTimeout(()=>{
this.showTips = true
},1000)
setTimeout(()=>{
this.showTips = false
},5000)
}
};
</script>
<style lang="less">
@import '../assets/iconfont.css';
@import './index.less';
</style>
<template>
<div class="drawer_container">
<div v-if="drawerType === 'grid'">
<div class="drawer_title">画布背景设置</div>
<div class="drawer_wrap">
<Form label-position="left" :label-width="85">
<FormItem label="是否显⽰⽹格" :label-width="100">
<i-switch v-model="showGrid" @on-change="changeGrid" />
</FormItem>
<div v-show="showGrid">
<FormItem label="⽹格类型">
<RadioGroup v-model="pe" @on-change="changeGridType">
<Radio v-for="item in gridTypeList" :label="item.value" :key="item.value">
<span>{{item.label}}</span>
</Radio>
</RadioGroup>
</FormItem>
<FormItem label="⽹格⼤⼩">
<Slider v-model="grid.size" :min="0" :max="30" @on-change="changeGrid"></Slider> </FormItem>
<FormItem label="⽹格颜⾊">
<ColorPicker v-model="lor" @on-change="changeGrid"/>
</FormItem>
<FormItem label="⽹格线宽度">
<Slider v-model="grid.args.thickness" :min="0" :max="20" @on-change="changeGrid"></Slider>
</FormItem>
</div>
</Form>
</div>
</div>
<div v-if="drawerType === 'node'">
<div class="drawer_title">节点设置</div>
<div class="drawer_wrap">
<Form label-position="left" :label-width="80">
<FormItem label="节点⽂本">
<Input v-model="deText" @on-change="changeNodeText"></Input>
</FormItem>
<FormItem label="节点背景">
<ColorPicker v-model="drawerNode.fill" @on-change="changeFill"/>
</FormItem>
<FormItem label="字体⼤⼩">
<Slider v-model="drawerNode.fontSize" :min="10" :max="20" @on-change="changefontSize"></Slider>
</FormItem>
<FormItem label="字体颜⾊">
<ColorPicker v-model="drawerNode.fontFill" @on-change="changeFontFill"/>
</FormItem>
<FormItem label="边框宽度">
<Slider v-model="drawerNode.strokeWidth" :min="0" :max="10" @on-change="changeStrokeWidth"></Slider> </FormItem>
<FormItem label="边框颜⾊">
<ColorPicker v-model="drawerNode.stroke" @on-change="changeStroke"/>
</FormItem>
<FormItem label="功能">
<Button type="primary" icon="md-trending-up" @click="toTopZIndex">置顶</Button>
<Button type="error" class="margin-left-10" icon="md-trash" @click="deleteNode">删除</Button>
</FormItem>
</Form>
</div>
</div>
<div v-if="drawerType === 'edge'">
<div class="drawer_title">线条设置</div>
<div class="drawer_wrap">
<Form label-position="left" :label-width="80">
<FormItem label="线条⽂本">
<Input v-model="drawerEdge.EdgeText" @on-change="changeEdgeText"></Input>
</FormItem>
<FormItem label="线条宽度">
<Slider v-model="drawerEdge.edgeWidth" :min="1" :max="10" @on-change="changeEdgeWidth"></Slider> </FormItem>
<FormItem label="线条颜⾊">
<ColorPicker v-model="drawerEdge.edgeColor" @on-change="changeEdgeColor"/>
</FormItem>
<FormItem label="功能">
<Button type="primary" icon="md-trending-up" @click="toTopZIndex">置顶</Button>
<Button type="error" class="margin-left-10" icon="md-trash" @click="deleteNode">删除</Button>
</FormItem>
</Form>
</div>
</div>
</div>
</template>
<script>
export default {
name:'RightDrawer',
data() {
return {
gridTypeList:[
{
label:'四边⽹格',
value:'mesh'
},
{
label:'点状⽹格',
value:'dot'
}
],
showGrid:true,
drawerNode:{
fill:'',
nodeText:'',
fontSize:null,
fontFill:'',
strokeWidth:null,
stroke:''
},
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论