В связи с потребностями компании требуется визуализация данных. Прочитав множество библиотек, я почувствовал, что библиотека D3.js очень мощная, поэтому решил использовать библиотеку D3.js. При использовании древовидной диаграммы я увидел фиксированную древовидную диаграмму и подумал, смогу ли я составить карту ума, поэтому начал исследовать. . .
//先进行NPM安装
npm i vued3tree
// 在页面中引用
import * as d3 from 'd3'
import {tree} from 'vued3tree'
html:
// 用的是ELEMENT-UI
<template>
<div class="main">
<div class="tb-menu" ref="main" :style="menuPos" v-show="isMenuShow" style="z-index: 1">
<div v-show="menuInfo.move" @click="menuClick('move')">删除节点</div>
<div v-show="menuInfo.inNextNode" @click="menuClick('inNextNode')">插入下一级节点</div>
<div v-show="menuInfo.inSameNode" @click="menuClick('inSameNode')">插入同级节点</div>
<div v-show="menuInfo.reName" @click="menuClick('reName')">重命名</div>
</div>
<div class="context">
<tree :data="tree" node-text="name" @clicked="addNode" @mouseup.stop="rClick($event,idx)" type="cluster" layoutType="euclidean">
</tree>
</div>
// 点击节点出现的弹窗
<el-dialog
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<div class="dialog" style="line-height: 50px">
<div style="margin-top: 20px;">
<span style="margin-right: 20px;">输入新节点名称</span>
<el-input v-model="newVal" placeholder="请输入内容"></el-input>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="handleExport">确 定</el-button>
</span>
</div>
</el-dialog>
<div>
</div>
</template>
JS:
export default {
components: {
tree,SoltTemp
},
data() {
return {
getNode: {},
showTree: false,
habit: '',
workHabit: '',
lifeHabit: '',
tree: {
name: "habit",
children:[{
name: "work",
children:[ {name: "watch skill's page", id: 1}, {name: "doing some new test", id: 2}]
},{
name: "life",
children:[ {name: "watch movie", id: 3}, {name: "run", id: 4},{name: "cookie", id: 4}]
}]
},
treeTwo: {},
menuPos: {
left: 500,
top: 500
},
isMenuShow: false,
menuInfo: {
move: true, // 移除
inNextNode: true, // 插入下一个节点
inSameNode: true, // 插入相同的节点
reName: true,
},
dialogVisible: false,
newVal: '',
type: ''
}
},
watch: {
'this.tree' (val) {
this.tree = JSON.parse(JSON.stringify(this.tree))
}
},
methods: {
yes() {
this.showTree = true
},
addHabit() {
this.tree.children.push({name: this.habit, id: this.tree.children[0].length + 1})
},
addWorkHabit() {
this.tree.children[0].children.push({name: this.workHabit, id: this.tree.children[0].children.length + 1})
this.tree = JSON.parse(JSON.stringify(this.tree))
},
addFileHabit() {
this.tree.children[1].children.push({name: this.lifeHabit, id: this.tree.children[1].children.length + 1})
},
addNode(type) {
this.getNode = type
// 对于点击事件进行取反操作
this.isMenuShow = !this.isMenuShow
this.menuPos.left = type.element.x + 1200 + 'px'
this.menuPos.top = type.element.y + 200 + 'px'
// 得到节点,就可以知道如何去插入
// 对插数据进行操作
},
menuClick(type) {
this.isMenuShow = false
this.type = type
if(type !== 'move') {
this.newVal = ''
this.dialogVisible = true
}
if(this.type == 'move') {
this.math(this.tree)
}
},
math(arr){
if(this.tree.name == this.getNode.data.name && this.type == 'inNextNode') {
this.tree.children.push({name: this.newVal, id: this.tree.children.length +1 })
} else {
arr.children.forEach((element, index) => {
if(element.name == this.getNode.data.name){
if(this.type == 'move') this.tree = Object.assign({}, this.tree, arr.children.splice(index,1))
if(this.type == 'reName') element.name = this.newVal
// 当选择下一条有没有孩子节点时所做的操作
if(this.type == 'inNextNode' && element.children) element.children.push({name: this.newVal, id: element.children.length + 1})
if(this.type == 'inNextNode' && !element.children) {
element.children = []
element.children.push({name: this.newVal, id:0})
this.$nextTick(() => {
//否则数据没有办法立即更新
this.tree = Object.assign({}, this.tree,element.children )
})
}
if(this.type == 'inSameNode') {
arr.children.push({name: this.newVal, id: arr.children.length + 1})
this.tree = Object.assign({}, this.tree,arr.children)
}
} else if(element.children){
this.math(element)
}
})
}
},
handleExport() {
this.dialogVisible = false
// 相同节点所作操作 常规的for循环 ---- 改进则使用递归
this.math(this.tree)
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
}
},
mounted() {
// 取消右键的点击事件
this.$el.querySelector('.context').oncontextmenu = () => { return false }
}
}
</script>
CSS
<style <style lang="scss" scoped>
.context {
display: flex;
justify-content: center;
margin: 0 auto;
width:500px;
height: 200px;
}
.tb-menu {
width: 180px;
padding: 8px 0;
position: absolute;
line-height: 30px;
top: 0;
left: 0;
background: #fff;
border: 1px solid #eee;
border-radius: 4px;
box-shadow: rgba(0, 0, 0, 0.12) 0px 2px 4px, rgba(0, 0, 0, 0.04) 0px 0px 6px;
div {
cursor: pointer;
padding: 6px 12px;
height:50px;
&:hover {
background: #eee;
}
span {
font-size: 12px;
color: #ccc;
}
}
el-dialog .dialog{
// height: 60vh;
line-height: 30px;
}
}
</style>
Итак, реализована простая интеллект-карта
снимок экрана:
Выполните операции узла:
Таким образом, простая карта разума может быть реализована~~
Продолжайте совершенствоваться в будущем~