实现树形结构的插件vue-tree-color及元素放大缩小拖动

2023-12-14 15:45:56

实现流程图,借鉴vue-tree-color

引入依赖

npm install vue-tree-color


同时查看项目中是否已安装less和less-loader,因为该组件使用到less

npm install --save-dev less less-loader


如果这里启动项目报错,有可能是less和less-loader的版本过高,可以降低版本,或者指定版本号

npm i less@3.9.0 less-loader@4.1.0 -D


添加全局

import Vue2OrgTree from 'vue-tree-color'
Vue.use(Vue2OrgTree)

目录结构

index copy.vue

<template>
  <!-- 组织架构 -->
  <div ref="appContainer" class="app-container">
    <div style="margin-left: 30px">
      <el-row :gutter="20">
        <el-col :span="5">
          <el-switch
            v-model="horizontal"
            :width="50"
            active-text="横排"
            inactive-text="竖排"
            style="margin-top: 8px"
          />
        </el-col>
        <el-col :span="5">
          <el-switch
            v-model="expandAll"
            :width="50"
            active-text="全部展开"
            inactive-text="全部折叠"
            style="margin: 8px"
            @change="expandChange"
          />
        </el-col>
      </el-row>
    </div>
    <div style="font-size: 12px; margin-top: 30px">
      <el-scrollbar :style="scrollTreeStyle" class="el-org-tree">
        <vue2-org-tree
          :data="treeData.data"
          :horizontal="!horizontal"
          :collapsable="collapsable"
          :label-class-name="treeData.labelClassName"
          :render-content="renderContent"
          name="organ"
          @on-expand="onExpand"
          @on-node-click="onNodeClick"
        />
      </el-scrollbar>
    </div>
    <br /><br />
  </div>
</template>
 
 
<script>
export default {
  name: "TreeTest",
  data() {
    return {
      treeData: {
        labelClassName: "bg-color-orange",
        basicInfo: { id: null, label: "---null" },
        basicSwitch: false,
        data: {
          id: 0,
          label: "XXX科技有限公司",
          children: [
            {
              id: 2,
              label: "产品研发部",
              children: [
                {
                  id: 5,
                  label: "研发-前端",
                  children: [
                    {
                      id: 55,
                      label: "前端1",
                    },
                    {
                      id: 56,
                      label: "前端2",
                    },
                    {
                      id: 57,
                      label: "前端3",
                    },
                    {
                      id: 58,
                      label: "前端4",
                    },
                  ],
                },
                {
                  id: 6,
                  label: "研发-后端",
                },
                {
                  id: 9,
                  label: "UI设计",
                },
                {
                  id: 10,
                  label: "产品经理",
                },
              ],
            },
            {
              id: 3,
              label: "销售部",
              children: [
                {
                  id: 7,
                  label: "销售一部",
                },
                {
                  id: 8,
                  label: "销售二部",
                },
              ],
            },
            {
              id: 4,
              label: "财务部",
            },
            {
              id: 9,
              label: "HR人事",
            },
          ],
        },
      },
      horizontal: true, //横版 竖版
      collapsable: false,
      expandAll: true, //是否全部展开

      scrollTreeStyle: "width:100%;",
    };
  },
  methods: {
    //渲染节点
    renderContent(h, data) {
      return (
        <div>
          <div>
            <i class="el-icon-user-solid"></i>
            <span>{data.label}</span>
            <span>男</span>
          </div>
          <div style="font-size:12px;line-height:20px;">测试人员</div>
        </div>
      );
    },

    //鼠标移出
    onMouseout(e, data) {
      this.treeData.basicSwitch = false;
    },
    //鼠标移入
    onMouseover(e, data) {
      this.treeData.basicInfo = data;
      this.treeData.basicSwitch = true;
      var floating = document.getElementsByClassName("floating")[0];
      floating.style.left = e.clientX + "px";
      floating.style.top = e.clientY + "px";
    },
    //点击节点
    NodeClick(e, data) {
      console.log(e, data);
    },
    //默认展开
    toggleExpand(data, val) {
      if (Array.isArray(data)) {
        data.forEach((item) => {
          this.$set(item, "expand", val);
          if (item.children) {
            this.toggleExpand(item.children, val);
          }
        });
      } else {
        this.$set(data, "expand", val);
        if (data.children) {
          this.toggleExpand(data.children, val);
        }
      }
    },
    collapse(list) {
      list.forEach((child) => {
        if (child.expand) {
          child.expand = false;
        }
        child.children && this.collapse(child.children);
      });
    },
    //展开
    onExpand(e, data) {
      if ("expand" in data) {
        data.expand = !data.expand;
        if (!data.expand && data.children) {
          this.collapse(data.children);
        }
      } else {
        this.$set(data, "expand", true);
      }
    },
    getList() {
      // 后台回去的数据 赋值给data即可
    },

    // 自定义您的点击事件
    onNodeClick(e, data) {
      alert("点击");
    },

    expandChange() {
      this.collapsable = true;
      this.toggleExpand(this.treeData.data, this.expandAll);
    },
  },
};
</script>
 

<style lang="less">

.org-tree-node-label-inner {
  color: #fff;
  background-color: orange;
}

.el-org-tree {
  .el-scrollbar__wrap {
    overflow-x: hidden;
  }
  .org-tree-node-label {
    white-space: nowrap;
  }
  .el-tree-node__content {
    background: white;
  }
  .org-tree-node-label .org-tree-node-label-inner {
    padding-top: 8px;
    padding-right: 10px;
    padding-bottom: 5px;
    padding-left: 10px;
    cursor: pointer;
  }
  .horizontal .org-tree-node.is-leaf {
    padding-top: 5px;
    padding-bottom: 5px;
  }
}
</style>

index.vue

<template>
  <!-- 元素放大缩小 拖动 -->
  <div
    id="drag"
    @mousewheel.prevent="changeCanvas($event)"
    @mousedown="mouseDrag($event)"
    @dragover="allowDrop($event)"
    @dragenter="dragEnter($event)"
    @mouseup="mouseUp($event)"
    @mousemove="mouseMove($event)"
  >
    <div id="flowContainer" ref="flowContainer">
      <simple-tree />
    </div>
  </div>
</template>
<script>
import simpleTree from "./index copy";
export default {
  name: "",
  components: {
    simpleTree,
  },
  computed: {},
  data() {
    return {
      msg: "111",
      zoomNum: 1,
      disX: null,
      disY: null,
      mainX: null,
      mainY: null,
      ifDrag: false,
    };
  },
  methods: {
    allowDrop(evt) {
      this.preventDefault(evt);
    },
    dragEnter(evt) {
      this.preventDefault(evt);
    },
    //阻止冒泡以及默认事件
    preventDefault(ev) {
      var evt = ev || window.event;
      if (typeof evt.preventDefault == "function") {
        evt.preventDefault();
      } else {
        evt.returnValue = false;
      }
      if (typeof evt.stopPropagation == "function") {
        evt.stopPropagation();
      } else {
        evt.cancelBubble = true;
      }
    },
    // ==漫游====
    // 拖拽
    mouseDrag(e) {
      // console.log('拖拽',e);
      this.linemove = false;
      // console.log(e)
      let _this = this;
      this.ifDrag = true;
      let pos = _this.getPos(e); //获取鼠标坐标
      _this.disX = pos.x;
      _this.disY = pos.y;
      _this.mainX = _this.$refs.flowContainer.offsetLeft;
      _this.mainY = _this.$refs.flowContainer.offsetTop-60;
      // if (this.ifDrag) {
      //   this.mouseMove(e);
      // }
    },
    mouseMove(e) {
      // console.log('move', document)
      var _this = this;
      // document.onmousemove = function (e) {
      //   debugger
      // console.log(e)
      //   e.preventDefault()
      if (!this.ifDrag) {
        return;
      }
      var evt = window.event || e;
      var left = evt.clientX - _this.disX + _this.mainX;
      var top = evt.clientY - _this.disY + _this.mainY;
      _this.$refs.flowContainer.style.left = left + "px";
      _this.$refs.flowContainer.style.top = top + "px";
      // }
      // this.mouseUp();
    },
    mouseUp() {
      // console.log('up', document.onmousemove)
      var _this = this;
      this.ifDrag = false;
      //鼠标抬起
      document.onmouseup = function (e) {
        // console.log(e)
        var evt = window.event || e;
        // document.onmousemove = null;
        // document.onmouseup = null;
        // _this.ifDrag = false;
      };
    },
    // 获取位置
    getPos(ev) {
      let scrollTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      let scrollLeft =
        document.documentElement.scrollLeft || document.body.scrollLeft;
      return { x: ev.clientX + scrollLeft, y: ev.clientY + scrollTop };
    },
    // 改变画布大小--通过鼠标滚轮 缩小,放大
    changeCanvas(event) {
      var delta = 0;
      var canvasDom = document.getElementById("flowContainer");
      var p = ["webkit", "moz", "ms", "o"];
      if (!event) event = window.event;
      if (event.wheelDelta) {
        //IE、chrome浏览器使用的是wheelDelta,并且值为“正负120”
        delta = event.wheelDelta / 120;
        if (window.opera) delta = -delta; //因为IE、chrome等向下滚动是负值,FF是正值,为了处理一致性,在此取反处理
      } else if (event.detail) {
        //FF浏览器使用的是detail,其值为“正负3”
        delta = -event.detail / 3;
      }
      if (delta > 0) {
        // 向上滚
        if (this.zoomNum < 2) {
          this.zoomNum += 0.1;
        }
      } else if (delta < 0) {
        // 向下滚
        if (this.zoomNum > 0.2) {
          this.zoomNum -= 0.1;
        }
      }
      for (var i = 0; i < p.length; i++) {
        canvasDom.style[p[i] + "Transform"] = "scale(" + this.zoomNum + ")";
      }
      canvasDom.style["transform"] = "scale(" + this.zoomNum + ")";
      return false;
    },
  },
  mounted() {
  },
  created() {},
  destroyed() {},
};
</script>

<style scoped>
#drag {
  width: 100%;
  height: 800px;
  background: #ccc;
  overflow: hidden;
}
#flowContainer {
  width: 100%;
  height: 100%;
  background: #fff;
  position: relative;
  overflow: hidden;
  left: 0px;
  top: 0px;
  transform-origin: 50% 50%;
}
</style>

文章来源:https://blog.csdn.net/boundle_ss/article/details/134995572
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。