实现如下效果图:包含,新增,编辑,删除功能.
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.offsetWidth
this.mindStyle.height = this.$refs.continer.offsetHeight
6.初始化mindmap
const that = this
const 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
当前思维导图的树形结构
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。楼主您好,可以把完整代码贴出来吗?