Because the company needs to do data visualization. After looking at many libraries, THE d3. js library is very powerful, so I decided to use the D3.js library. When I was using a tree, I saw a fixed tree and wondered if I could do a mind map, so I started exploring…

NPM I vued3tree import * as d3 from'd3'
import {tree} from 'vued3tree'
Copy the code

html:

// use elder-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')"> Delete node </div> <div v-show="menuInfo.inNextNode" @click="menuClick('inNextNode')"> Insert the next level node </div> <div v-show="menuInfo.inSameNode" @click="menuClick('inSameNode')"<div v-show= <div v-show="menuInfo.reName" @click="menuClick('reName')"> rename </div> <div class="context">
            <tree :data="tree" node-text="name" @clicked="addNode"  @mouseup.stop="rClick($event,idx)" type="cluster" layoutType="euclidean"> </tree> </div> // Click on the node to appear the popup <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;"> Enter a new node name </span> <el-input V-model ="newVal" placeholder="Please enter the content"></el-input>
              </div>
              <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false"</el-button> <el-buttontype="primary" @click="handleExport"> determine < / el - button > < / span > < / div > < / el - dialog > < div > < / div > < / template >Copy the code

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/ / removedinNextNode: true// Insert the next nodeinSameNode: true, // Insert the same node 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 = typeThis.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 // The operation to do when selecting the next node with or without childrenif(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(() = > {/ / otherwise data can't update now enclosing tree = Object. The assign ({}, this tree, element. The 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// The operation on the same node is normalforMath (this.tree)}, handleClose(done) {
    this.$confirm('Confirmed closure? ')
      .then(_ => {
        done();
      })
      .catch(_ => {});
    }
  },
  mounted() {// Cancel the right click event this.$el.querySelector('.context').oncontextmenu = () => { return false }
  }
}
</script>

Copy the code

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>
Copy the code

Thus, a simple mind map is achieved

Screenshots:

Perform node operations:

So a simple mind map can be realized

Continue to improve ~