实现如下效果图:蕴含,新增,编辑,删除性能.
1.首先装置G6
2.创立vue页面,
3.在页面中引入G6
import G6 from '@antv/g6'const { Util } = G6
4.创立页面容器<div id="myMap" />
5.在mounted中获取容器宽高
this.mindStyle.width = this.$refs.continer.offsetWidththis.mindStyle.height = this.$refs.continer.offsetHeight
6.初始化mindmap
const that = thisconst borderStyle = 'height: 42, stroke: #70A2E1, radius: 6, fill: #DCE6F2, lineWidth: 2'const labelStyle = 'fontSize: 16, marginTop: 13, marginLeft: 16, marginRight:16'const tipStyle = 'marginTop: -15, stroke: #409EFF, fill: #409EFF, cursor: pointer'const position = [[0, 0.5], [1, 0.5]]G6.registerNode( 'dice-mind-map-root', { jsx: (cfg) => { const width = Util.getTextSize(cfg.label, 16)[0] + 50 return ` <group> <rect draggable="true" style={{width: ${width}, ${borderStyle}}} keyshape> <text style={{ ${labelStyle} }}>${cfg.label}</text> ${type === 'add' ? '' : `<text style={{ marginLeft: ${width - 16}, ${tipStyle}, opacity: ${cfg.hover ? 0.75 : 0} }} action="add">+</text>`} </rect> </group>` }, getAnchorPoints() { return position } }, 'single-node') G6.registerNode( 'dice-mind-map-sub', { jsx: (cfg) => { const width = Util.getTextSize(cfg.label, 16)[0] + 50 return ` <group> <rect draggable="true" style={{width: ${width},${borderStyle}}} keyshape> <text draggable="true" style={{ ${labelStyle} }}>${cfg.label}</text> ${type === 'add' ? '' : `<text style={{ marginLeft: ${width - 30}, ${tipStyle}, opacity: ${cfg.hover ? 0.75 : 0}, next: 'inline' }} action="add">+</text>`} ${type === 'add' ? '' : `<text style={{ marginLeft: ${width - 20}, ${tipStyle}, opacity: ${cfg.hover ? 0.75 : 0}, next: 'inline' }} action="delete">-</text>`} </rect> </group>` }, getAnchorPoints() { return position } }, 'single-node' ) G6.registerBehavior('dice-mindmap', { getEvents() { if (type !== 'add') { return { 'node:click': 'clickNode', 'node:dblclick': 'editNode', 'node:mouseenter': 'hoverNode', 'node:mouseleave': 'hoverNodeOut' } } }, clickNode(evt) { const model = evt.item.get('model') const name = evt.target.get('action') switch (name) { case 'add': that.nodeAdd(model, evt) break case 'delete': this.nodeDelete(model, evt) break case 'edit': break default: return } }, editNode(evt) { that.nodeEdit(evt) }, hoverNode(evt) { that.nodeHover(evt, true) }, hoverNodeOut(evt) { that.nodeHover(evt, false) } }) this.mindmap = new G6.TreeGraph({ container: 'myMap', width: this.mindStyle.width, height: this.mindStyle.height, fitView: 'autoSize', fitViewPadding: [10, 20], layout: { type: 'mindmap', direction: 'H', getHeight: () => { return 40 }, getWidth: (node) => { return node.level === 0 ? Util.getTextSize(node.label, 16)[0] + 20 : Util.getTextSize(node.label, 12)[0] }, getVGap: () => { return 10 }, getHGap: () => { return 60 }, getSide: (node) => { return node.data.direction } }, // 边的款式 defaultEdge: { type: 'cubic-horizontal', style: { lineWidth: 2, stroke: '#C3D8F2' } }, // 文字款式 defaultNode: { labelCfg: { style: { fill: '#333', fontSize: 20 } }, style: { stroke: '#72CC4A', width: 150 } }, minZoom: 0.5, modes: { default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'] } }) this.mindmap.data(that.dataFormat(this.treeNode)) this.mindmap.render()
7.鼠标移入事件,显示增加删除按钮
nodeHover(evt, status) { evt.currentTarget.updateItem(evt.item, { hover: status })},
8.节点编辑事件,双击能够编辑文本内容
nodeEdit(evt) { const item = evt.item const model = item.get('model') const { x, y } = item.calculateBBox() const graph = evt.currentTarget const realPosition = evt.currentTarget.getClientByPoint(x, y) const el = document.createElement('div') const fontSizeMap = { 'dice-mind-map-root': 24, 'dice-mind-map-sub': 18 } el.style.fontSize = fontSizeMap[model.type] + 'px' el.style.position = 'fixed' el.style.top = realPosition.y + 'px' el.style.left = realPosition.x + 'px' el.style.paddingLeft = '12px' el.style.transformOrigin = 'top left' el.style.transform = `scale(${evt.currentTarget.getZoom()})` const input = document.createElement('input') input.style.border = 'none' input.value = model.label input.style.width = Util.getTextSize(model.label, fontSizeMap[model.type])[0] + 15 + 'px' input.className = 'dice-input' el.className = 'dice-input' el.appendChild(input) document.body.appendChild(el) const destroyEl = () => { document.body.removeChild(el) } const clickEvt = (event) => { if (!(event.target && event.target.className && event.target.className.includes('dice-input'))) { window.removeEventListener('mousedown', clickEvt) window.removeEventListener('scroll', clickEvt) graph.updateItem(item, { label: input.value }) graph.layout(false) graph.off('wheelZoom', clickEvt) destroyEl() } } graph.on('wheelZoom', clickEvt) window.addEventListener('mousedown', clickEvt) window.addEventListener('scroll', clickEvt) input.addEventListener('keyup', (event) => { if (event.key === 'Enter') { clickEvt({ target: {} }) } }) },
9.节点增加事件
nodeAdd(model, evt) { const newId = model.id + '-' + (((model.children || []).reduce((a, b) => { const num = Number(b.id.split('-').pop()) return a < num ? num : a }, 0) || 0) + 1) evt.currentTarget.updateItem(evt.item, { children: (model.children || []).concat([{ id: newId, direction: newId.charCodeAt(newId.length - 1) % 2 === 0 ? 'right' : 'left', label: '子节点', type: 'dice-mind-map-sub', color: model.color }]) }) evt.currentTarget.layout(false) },
10.节点删除事件
nodeDelete(model, evt) { const parent = evt.item.get('parent') evt.currentTarget.updateItem(parent, { children: (parent.get('model').children || []).filter((e) => e.id !== model.id) }) evt.currentTarget.layout(false) },
11.数据格式化
dataFormat(data) { const changeData = (d, level = 0) => { const data = { ...d } switch (level) { case 0: data.type = 'dice-mind-map-root' break case 1: data.type = 'dice-mind-map-sub' break default: data.type = 'dice-mind-map-sub' break } data.hover = false if (level === 1 && !d.direction) { if (!d.direction) { data.direction = d.id.charCodeAt(d.id.length - 1) % 2 === 0 ? 'right' : 'left' } } if (d.children) { data.children = d.children.map((child) => changeData(child, level + 1, data.color)) } return data } return changeData(data) },
12.切换显示时,先销毁this.mindmap.destroy()
13.向后盾提交数据this.mindmap.getNodes()
查看所有节点信息this.mindmap.getNodes()[0]._cfg.model
以后思维导图的树形构造
.