100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > antv-g6—在vue项目中实现网格拓扑流程图自定义绘制

antv-g6—在vue项目中实现网格拓扑流程图自定义绘制

时间:2022-09-07 03:21:30

相关推荐

antv-g6—在vue项目中实现网格拓扑流程图自定义绘制

实现效果图

这个是自己写着玩的,利用@antv/g6自定义绘制流程图,然后保存到localstorage中,在左侧表格展示,还可以通过表格操作来查看对应的流程图以及删除;

这里特别注意一下,@antv/g6版本是1.2.8,vue版本是2.5.x;

下面我会把实现代码全部粘贴出来,不需要需改,开袋即食,放到你的项目中直接可以展示;

代码中我也会加上注释,不懂的可以看注释;

流程图组件

flow.vue

<template><div id="flowChart"><!-- 头部工具栏 --><div class="operating"><div class="btn-group"><div class="btn" @click="addCircle" title="开始节点"><i class="iconfont icon-weixuanzhongyuanquan"></i></div><div class="btn" @click="addRect" title="普通节点"><i class="iconfont icon-gl-square"></i></div><div class="btn" @click="addRhombus" title="条件节点"><i class="iconfont icon-tubiao"></i></div></div><div class="btn-group"><div class="btn" @click="addLine" title="直线"><i class="iconfont icon-line"></i></div><div class="btn" @click="addSmooth" title="曲线"><i class="iconfont icon-byangtiaoquxian"></i></div><div class="btn" @click="addArrowLine" title="箭头直线"><i class="iconfont icon-gl-arrowRd"></i></div><div class="btn" @click="addArrowSmooth" title="箭头曲线"><i class="iconfont icon-a-18"></i></div></div><div class="btn-group"><div class="btn" @click="changeMode('edit')" title="选择模式"><i class="iconfont icon-xuanze"></i></div><div class="btn" @click="changeMode('drag')" title="拖拽模式"><i class="iconfont icon-tuozhuai"></i></div></div><div class="btn-group"><div class="btn" @click="del" style="margin-top: 5px;" title="删除"><i class="el-icon-delete"></i></div><div class="btn" @click="save" title="保存"><i class="iconfont icon-baocun"></i></div></div><div class="btn-group"><el-input size="mini" v-model="workflowName" placeholder="请输入流图名称..."></el-input></div></div><!-- 右侧节点属性设置 --><div class="info"><div class="title"><span>{{infoTitle}}属性</span></div><div class="content"><el-checkbox v-if="isBlank === true" v-model="checked">网格对齐</el-checkbox><el-form v-else label-position="left" label-width="60px"><el-form-item v-if="isNode !== true" label="动作"><el-select v-model="action" size="mini" filterable placeholder="绑定动作" value=""><el-optionv-for="item in actionList":key="item.id":label="item.label":value="item.id"></el-option></el-select></el-form-item> <!-- 线--><el-form-item v-if="isNode === true" label="名称"><el-input size="mini" v-model="name"></el-input></el-form-item><!-- <el-form-item v-if="isNode === true" label="类型"><el-select v-model="nodeType" size="mini" filterable placeholder="请选择类型" value=""><el-optionv-for="item in nodeTypeList":key="item.id":label="item.label":value="item.id"></el-option></el-select></el-form-item> --><el-form-item label="颜色"><el-color-picker v-model="color"></el-color-picker></el-form-item></el-form></div></div></div></template><script>import G6 from '@antv/g6';export default {mounted() {this.initG6();},props: {actionList: {type: Array, default: []},nodeTypeList: {type: Array, default: () => {return [{id: '001', label: '普通节点'},{id: '002', label: '开始节点'},]}}},data() {return {action: '',name: '',nodeType: 0,color: '',net: '',Util: '',workflowName: '',activation: '', //当前激活的节点isNode: false, //当前是节点isBlank: true, //当前是空白区checked: true, //网格对齐infoTitle: '画布',//属性标题oldColor: '', //获取节点本身颜色type: '', //有值为编辑状态}},methods: {//初始化initG6() {let self = this;self.Util = G6.Util;let grid;if (self.checked) {grid = {forceAlign: true, // 是否支持网格对齐cell: 25, // 网格大小};} else {grid = null;} = new ({id: 'flowChart',// 容器IDmode: 'edit',grid: grid,/*width: 500, // 画布宽*/height: 800 // 画布高});/***点击空白处*/.on('click', (ev) => {if (!self.Util.isNull(ev.item)) {self.isBlank = false} else {self.isBlank = true;self.infoTitle = '画布'}});/***点击节点*/.on('itemclick', function (ev) {self.isNode = self.Util.isNode(ev.item); //是否为Nodeself.activation = ev.item;if (self.isNode) {/* 激活节点后节点名称input聚焦*/self.$nextTick(()=>{self.$refs.inputFocus.$el.querySelector('input').focus();});self.infoTitle = '节点';self.name = ev.item.get('model').label;self.nodeType = ev.item.get('model').nodeType;} else {self.infoTitle = '边';self.action = ev.item.get('model').action;}self.color = self.oldColor;});/*** 鼠标移入移出事件改变颜色*/.on('itemmouseenter', ev => {const item = ev.item;self.oldColor = item.get('model').color;//获取节点颜色.update(item, {color: '#108EE9',});.refresh();});.on('itemmouseleave', ev => {const item = ev.item;.update(item, {color: self.oldColor});.refresh();});/*.source(self.nodes, self.edges);*/ //加载资源数据.render();},//添加起始节点addCircle() {.beginAdd('node', {shape: 'circle',nodeType: 0})},//添加常规节点addRect() {.beginAdd('node', {shape: 'rect',nodeType: 0})},//添加条件节点addRhombus() {.beginAdd('node', {shape: 'rhombus',nodeType: 0})}, //添加直线addLine() {.beginAdd('edge', {shape: 'line'});}, //添加曲线addSmooth() {.beginAdd('edge', {shape: 'smooth'})}, //添加箭头曲线addArrowSmooth() {.beginAdd('edge', {shape: 'smoothArrow'})}, //添加箭头直线addArrowLine() {.beginAdd('edge', {shape: 'arrow'});}, //添加折线addPolyLine() {.beginAdd('edge', {shape: 'polyLineFlow'});}, //拖拽与编辑模式的切换changeMode(mode) {.changeMode(mode)}, //删除节点del() {.del()},//保存流程图save() {/* 验证流图名称*/if (this.workflowName !== '') {let data = .save();if (data.source.nodes.length === 0) {this.$message({type: 'error', message: '流图内容不能为空'});return false}/* 验证节点名称*/for (let item of data.source.nodes) {if (item.label === '' || item.label === null || item.label === undefined) {this.$message({type: 'error', message: '节点名称不能为空'});return false}}data.source['name'] = this.workflowName;/*let json = JSON.stringify(data, null, 2);*/this.$emit('saveData', data.source, this.type);} else {this.$message({type: 'error', message: '流图名称不能为空'})}/*console.log(saveData, json);*/},//更新节点update() {if (this.activation.get('type') === 'node') {.update(this.activation, {label: this.name,nodeType: this.nodeType,color: this.color});} else {/* 根据ID取出label*/let label = this.actionList.map(item => {if (item.id === this.action) {return item.label}}).join('');.update(this.activation, {label: label,color: this.color,action: this.action});}},//清空视图,重置画布clearView() {this.type = '';this.workflowName = '';.changeData()},//渲染流程数据source(nodes, edges, name, type) {this.type = type;this.workflowName = name;.changeData(nodes, edges)}, },watch: {/*** 监听输入框*/action: function () {this.update()},name: function () {this.update()},nodeType: function () {this.update()},color: function () {this.update()},/*** 网格切换*/checked: function () {let _saveData = .save();.destroy(); //销毁画布this.initG6();.read(_saveData);.render()}}}</script><style lang="less" scoped>#flowChart {border: 1px solid #cdcdcd;border-radius: 5px;position: relative;overflow: hidden;width: 80%;box-sizing: border-box;height: 100%;}.operating {position: absolute;z-index: 99;background-color: #ffffff;padding: 20px 10px;box-shadow: 1px 1px 4px 0 #0a0a0a2e;}.info {position: absolute;height: 100%;right: 0;z-index: 99;box-shadow: 1px 1px 4px 0 #0a0a0a2e;.title {height: 40px;padding-left: 10px;border-top: 1px solid #DCE3E8;border-bottom: 1px solid #DCE3E8;border-left: 1px solid #DCE3E8;background: rgb(235, 238, 242);line-height: 40px;span {font-size: 14px;}}.content {background: rgba(247, 249, 251, 0.45);width: 220px;height: 800px;border-left: 1px solid #E6E9ED;padding: 10px;}}.btn-group {border-right: 1px solid #efefef;display: inline-block;padding-left: 10px;padding-right: 14px;&:last-of-type {border-right: 0;}.btn {display: inline-block;margin: 2px;width: 30px;height: 30px;line-height: 30px;text-align: center;cursor: pointer;border: 1px solid rgba(233, 233, 233, 0);i {font-size: 20px;}&:hover {border: 1px solid #E9E9E9;color: #767A85;border-radius: 2px;background: #FAFAFE;}}.el-form-item {margin-bottom: 0 !important;}}</style>

使用流程组件

<template><div class="flow_content"><div class="table_content"><el-button size="small" type="primary" style="margin: 10px 0;" @click="newAdd">新建流程</el-button>. <el-table:data="tableData"borderhighlight-current-row=truestyle="width: 100%"><el-table-columnprop="name"align="center"label="名称"></el-table-column><el-table-columnlabel="操作"align="center"width="100"><template slot-scope="scope"><el-button type="text" size="small"@click.native.prevent="viewFlow(scope.row)">查看</el-button><el-button type="text" size="small"@click.native.prevent="deleteRow(scope.$index, scope.row)">移除</el-button></template></el-table-column></el-table></div><flowChartref="flow":actionList="actionList"@saveData="saveData"></flowChart></div></template><script>import flowChart from './components/flow.vue'import {v4 as uuidv4 } from "uuid";export default {data(){return {actionList:[{id:'001',label:'拒绝'},{id:'002',label:'通过'},{id:'003',label:'下发'}],tableData:[],clickName:"",//当前点击渲染的流程图}},components:{flowChart},mounted(){//初始化获取列表数据,如果有数据,画布就展示第一个流程,如果没有数据就为空集合var tables = localStorage.getItem('flowTable')if(tables){this.tableData = JSON.parse(tables)const {nodes, edges, name, type} = this.tableData[0]this.$refs.flow.source(nodes, edges, name, type)}else{this.tableData = []}},methods:{saveData(source,type){var isHave = falsevar indexNum var filterTableData = this.tableData.filter( item => {return item.type !== type})filterTableData.forEach( (item,index) => {if(item.name == source.name){isHave = trueindexNum = index}})if(type){//type有值,编辑if(isHave){//编辑的名称已存在this.$message({message: '该名称已存在!',type: 'warning'});}else{var obj = sourceobj.type = typethis.tableData.splice(indexNum, 1,obj);this.$message({message: '保存成功!',type: 'success'});}}else{if(!isHave){//type无值,新建let uid = uuidv4()var obj = sourceobj.type = uidthis.tableData.push(source)this.$message({message: '保存成功!',type: 'success'});}else{this.$message({message: '该名称已存在!',type: 'warning'});}}var tables = JSON.stringify(this.tableData)localStorage.setItem('flowTable',tables)},//点击查看流程图viewFlow(row){this.clickName = row.namethis.$refs.flow.clearView()const {nodes, edges, name, type} = rowthis.$refs.flow.source(nodes, edges, name, type)},//新建流程图,清空画布newAdd(){this.$refs.flow.clearView()},//删除单个列表并清空当前删除的画布deleteRow(index, row) {var leng = this.tableData.lengthif(this.clickName == row.name || index == leng -1 || leng == 0){this.$refs.flow.clearView()}this.tableData.splice(index, 1);var tables = JSON.stringify(this.tableData)localStorage.setItem('flowTable',tables)}}}</script><style lang="less" scoped>.flow_content{height: 100%;display: flex;justify-content: space-around;.table_content{width: 19%;box-sizing: border-box;border: 1px solid #cdcdcd;border-radius: 5px;padding: 0 10px;}}</style>

以上就是上面效果图实现的全部代码,没有什么技术含量,就是简单的记录下来,分享给有需要的人;

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。