原文首發於個人博客,歡迎點擊查看得到更好的閱讀體驗~
最新版本css
請關注G6官方的github倉庫https://github.com/antvis/g6html
2.x版本後,能夠經過
npm install
直接安裝使用了
相關資源下載vue
最近我司項目中須要加入流程圖製做功能,因而乎百度各類找可視化繪製拓撲圖的輪子,大部分都是國外的,看文檔太吃力,不過好在最終讓我發現了AntV G6流程圖圖表庫,最新版爲2.0,不過編輯器在2.0版本尚未進行開源,因此只能退而求其次,使用了1.2.8版本。但願2.0版本的編輯器儘早開源,在交互方面1.2.8版本仍是差了一些。該組件並
非開箱即食
,須要根據本身的業務進行修改,右側屬性表單部分若是有時間考慮改成插槽形式,方便之後複用~node
v2.0.1
v2.4.5
v1.2.8
在index.html
中進行了全局引用git
<script src="./static/plugin/g6.min.js"></script>
仿照2.0版本的編輯器將G6做爲了一個組件使用,代碼:github
<template> <div id="flowChart"> <div class="operating"> <div class="btn-group"> <div class="btn" @click="addCircle" title="起始節點"> <i class="iconfont icon-circle-oeps"></i> </div> <div class="btn" @click="addRect" title="常規節點"> <i class="iconfont icon-square-oeps"></i> </div> <div class="btn" @click="addRhombus" title="條件節點"> <i class="iconfont icon-square-ling"></i> </div> </div> <div class="btn-group"> <div class="btn" @click="addLine" title="直線"> <i class="iconfont icon-zhixian"></i> </div> <div class="btn" @click="addSmooth" title="曲線"> <i class="iconfont icon-quxian"></i> </div> <div class="btn" @click="addArrowLine" title="箭頭直線"> <i class="iconfont icon-jiantouzhixian"></i> </div> <div class="btn" @click="addArrowSmooth" title="箭頭曲線"> <i class="iconfont icon-jiantouquxian"></i> </div> </div> <div class="btn-group"> <div class="btn" @click="changeMode('edit')" title="選擇模式"> <i class="iconfont icon-chose"></i> </div> <div class="btn" @click="changeMode('drag')" title="拖拽模式"> <i class="iconfont icon-move"></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-option v-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="func" size="mini" filterable placeholder="綁定功能" value=""> <el-option v-for="item in funcList" :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-select v-model="account" size="mini" filterable multiple collapse-tags placeholder="綁定帳號" value=""> <el-option v-for="item in accountList" :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-select v-model="workflow" size="mini" filterable clearable placeholder="綁定流圖" value=""> <el-option v-for="item in workflowList" :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-select v-model="nodeType" size="mini" filterable placeholder="請選擇類型" value=""> <el-option v-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> export default { name: "index", components: {}, mounted() { this.initG6(); }, props: { actionList: { type: Array, default: [] }, funcList: { type: Array, default: [] }, accountList: { type: Array, default: [] }, workflowList: { type: Array, default: [] }, nodeTypeList: { type: Array, default: () => { return [ {id: 0, label: '普通節點'}, {id: 1, label: '入口節點'}, {id: 2, label: '出口節點'} ] } } }, data() { return { action: '', name: '', func: '', account: '', workflow: '', 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; } self.net = new G6.Net({ id: 'flowChart', // 容器ID mode: 'edit', grid: grid, /*width: 500, // 畫布寬*/ height: 800 // 畫布高 }); /*self.net.tooltip({ title: '信息', // @type {String} 標題 split: ':', // @type {String} 分割符號 dx: 0, // @type {Number} 水平偏移 dy: 0 // @type {Number} 豎直偏移 });*/ /** *點擊空白處 */ self.net.on('click', (ev) => { if (!self.Util.isNull(ev.item)) { self.isBlank = false } else { self.isBlank = true; self.infoTitle = '畫布' } }); /** *點擊節點 */ self.net.on('itemclick', function (ev) { self.isNode = self.Util.isNode(ev.item); //是否爲Node self.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.func = ev.item.get('model').func; self.account = ev.item.get('model').account || []; self.workflow = ev.item.get('model').workflow; self.nodeType = ev.item.get('model').nodeType; } else { self.infoTitle = '邊'; self.action = ev.item.get('model').action; } self.color = self.oldColor; }); /** * 鼠標移入移出事件改變顏色 */ self.net.on('itemmouseenter', ev => { const item = ev.item; self.oldColor = item.get('model').color; //獲取節點顏色 self.net.update(item, { color: '#108EE9', }); self.net.refresh(); }); self.net.on('itemmouseleave', ev => { const item = ev.item; self.net.update(item, { color: self.oldColor }); self.net.refresh(); }); /** * 提示信息 */ /* self.net.node().tooltip(['label', 'func', 'role', 'color']); self.net.edge().tooltip(['label', 'color']);*/ /** * 渲染 */ /*self.net.source(self.nodes, self.edges);*/ //加載資源數據 self.net.render(); }, addCircle() { this.net.beginAdd('node', { shape: 'circle', nodeType: 0 }) },//添加起始節點 addRect() { this.net.beginAdd('node', { shape: 'rect', nodeType: 0 }) },//添加常規節點 addRhombus() { this.net.beginAdd('node', { shape: 'rhombus', nodeType: 0 }) }, //添加條件節點 addLine() { this.net.beginAdd('edge', { shape: 'line' }); }, //添加直線 addSmooth() { this.net.beginAdd('edge', { shape: 'smooth' }) }, //添加曲線 addArrowSmooth() { this.net.beginAdd('edge', { shape: 'smoothArrow' }) }, //添加箭頭曲線 addArrowLine() { this.net.beginAdd('edge', { shape: 'arrow' }); }, //添加箭頭直線 addPolyLine() { this.net.beginAdd('edge', { shape: 'polyLineFlow' }); }, //添加折線 changeMode(mode) { this.net.changeMode(mode) }, //拖拽與編輯模式的切換 del() { this.net.del() },//刪除 save() { /* 驗證流圖名稱*/ if (this.workflowName !== '') { let data = this.net.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') { this.net.update(this.activation, { label: this.name, func: this.func, account: this.account, workflow: this.workflow, nodeType: this.nodeType, color: this.color }); } else { /* 根據ID取出label*/ let label = this.actionList.map(item => { if (item.id === this.action) { return item.label } }).join(''); this.net.update(this.activation, { label: label, color: this.color, action: this.action }); } }, //更新節點 clearView() { this.type = ''; this.workflowName = ''; this.net.changeData() }, //清空視圖 source(nodes, edges, name, type) { this.type = type; this.workflowName = name; this.net.changeData(nodes, edges) }, //更新數據 }, watch: { /** * 監聽輸入框 */ action: function () { this.update() }, name: function () { this.update() }, func: function () { this.update() }, account: function () { this.update() }, workflow: function () { this.update() }, nodeType: function () { this.update() }, color: function () { this.update() }, /** * 網格切換 */ checked: function () { let _saveData = this.net.save(); this.net.destroy(); //銷燬畫布 this.initG6(); this.net.read(_saveData); this.net.render() } } } </script> <style rel="stylesheet/scss" lang="scss" scoped> #flowChart { border: 1px solid #ebeef5; position: relative; overflow: hidden; } .operating { position: absolute; z-index: 99; background-color: #ffffff; padding: 20px 10px; box-shadow: 1px 1px 4px 0 #0a0a0a2e; } .info { position: absolute; 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: 200px; 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>
參數 | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
actionList | 動做數據 | Array | —— | [] |
funcList | 功能數據 | Array | —— | [] |
accountList | 帳號數據 | Array | —— | [] |
workflowList | 流圖數據 | Array | —— | [] |
nodeTypeList | 節點類型數據 | Array | —— | [{id: 0, label: '普通節點'},{id: 1, label: '入口節點'},{id: 2, label: '出口節點'}] |
全部屬性接收的數據格式須要與
nodeTypeList
的默認值相同
事件名 | 說明 | 參數 |
---|---|---|
saveData | 當用戶手動點擊保存觸發事件 | source,type |
參數type
可爲空,在此項目中主要用來區分新建
與編輯
方法名 | 說明 | 參數 |
---|---|---|
clearView | 清空當前視圖 | —— |
source | 渲染數據 | nodes, edges, name, type |
參數type
與事件中相同,參數name
的做用是用來取流圖名
舊版本G6 1.x API 文檔json