jsPlumb是一个比较强大的绘图组件,它提供了一种方法,主要用于连接网页上的元素。在现代浏览器中,它使用SVG或者Canvas技术,而对于IE8以下(含IE8)的浏览器,则使用VML技术。

在这里插入图片描述

  1. 安装

npm install jsplumb --save

  1. main.js 引入

import jsPlumb from 'jsplumb'
Vue.prototype.$jsPlumb = jsPlumb.jsPlumb

  1. 示例代码
<!--
 * @Descripttion: 使用jsplumb插件实现连线功能
 * @version:
 * @Author: zhangfan
 * @email: 2207044692@qq.com
 * @Date: 2021-10-15 17:27:24
 * @LastEditors: zhangfan
 * @LastEditTime: 2022-06-02 10:38:39
-->
<template>
  <div class="content" id="plumbContent">
    <div class="left">
      <div class="top">项目</div>
      <ul class="bottom" id="leftBottom">
        <li
          v-for="(item, index) in leftData"
          :key="index"
          :id="item.id"
          name="source"
        >
          {{ item.label }}
        </li>
      </ul>
    </div>
    <div class="right">
      <div class="top">负责人</div>
      <ul class="bottom" id="rightBottom">
        <li
          v-for="item in rightData"
          :key="item.id"
          :id="item.name"
          name="target"
          class="itemLi"
        >
          <div>{{ item.name }}</div>
        </li>
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      leftData: [
        {
          id: 1,
          label: "项目1",
        },
        {
          id: 2,
          label: "项目2",
        },
        {
          id: 3,
          label: "项目3",
        },
        {
          id: 4,
          label: "项目4",
        },
        {
          id: 5,
          label: "项目5",
        },
        {
          id: 6,
          label: "项目6",
        },
      ],
      rightData: [
        {
          id: 1,
          name: "张三",
        },
        {
          id: 2,
          name: "李四",
        },
        {
          id: 3,
          name: "王五",
        },
      ],
      plumbins: null, // 缓存实例化的jsplumb对象
      connection: [],
      connectionList: [], //手动维护一个关系
    };
  },
  methods: {
    init() {
      //   初始化实例
      this.$jsPlumb.ready(() => {
        this.plumbins = this.$jsPlumb.getInstance({
          Container: "plumbContent", // 选择器id
          Connector: ["Straight"], //直线连接
        });
        // 双击删除连线
        this.plumbins.bind("dblclick", (connection, originalEvent) => {
          this.plumbins.deleteConnection(connection);
        });
        this.plumbins.bind("connection", (conn, originEvent) => {
          // 数据存入
          let obj = {};
          obj.sourceId = conn.sourceId;
          obj.targetId = conn.targetId;
          console.log(obj);
          console.log(this.plumbins.getConnections()); //获取连线数据
        });
        this.plumbins.batch(() => {
          this.leftData.forEach((item, index) => {
            this.initNode(item.id, "source");
          });
          this.rightData.forEach((item, index) => {
            this.initNode(item.name, "target");
          });
        });
        // 添加列表支持滚动
        this.plumbins.addList(leftBottom);
        this.plumbins.addList(rightBottom);
      });
    },
    initNode(id, type) {
      // 初始化点使其可以连接
      const ins = this.plumbins;
      const elements = document.getElementById(id);
      if (type === "source") {
        ins.makeSource(elements, {
          // 锚点
          anchor: [1, 0.5, 0, 0],
          allowLoopback: false,
          maxConnections: 1, //一对一就把maxConnections设置为1,一对多就设置为-1
          //   锚点样式
          paintStyle: {
            fill: "skyblue",
            strokeWidth: 3,
            radius: 5,
          },
          hoverPaintStyle: { fill: "red" },
          //   连线样式
          connectorStyle: {
            outlineStroke: "skyblue",
            strokeWidth: 3,
          },
          connectorHoverStyle: {
            strokeWidth: 6,
            stroke: "red",
            outlineStroke: "red",
          },
        });
      } else {
        ins.makeTarget(elements, {
          anchor: [0, 0.5, 1, 0], // 锚点
          //   锚点样式
          paintStyle: {
            strokeWidth: 2,
            radius: 20,
          },
          allowLoopback: false,
          maxConnections: -1, //一对一就把maxConnections设置为1,一对多就设置为-1
          paintStyle: {
            fill: "skyblue",
            strokeWidth: 3,
            radius: 5,
          },
          endpointHoverStyle: { fill: "red" },
        });
      }
    },
    setjsPlumb(sourceFlag, targetFlag) {
      const source = document.getElementsByName("source");
      const target = document.getElementsByName("target");

      this.plumbins.setSourceEnabled(source, sourceFlag);
      this.plumbins.setTargetEnabled(target, targetFlag);
      this.plumbins.setDraggable(source, true); // 是否支持拖拽
      this.plumbins.setDraggable(target, true); // 是否支持拖拽
    },
    repaintPlumb() {
      this.plumbins.repaintEverything();
    },
    repaintConnetion(connetionList) {
      if (this.$store.state.lines.connetions.length != 0) {
        let connect = this.$store.state.lines.connetions.concat([]);
        this.$nextTick(() => {
          // 根据commonJS中的列表重新划线
          connect.forEach((item) => {
            this.plumbins.connect({
              source: item.sourceId,
              target: item.targetId,
            });
          });
        });
      }
    },
    // 保存连线关系
    getConnetion() {
      this.connection = this.plumbins.getConnections();
    },
  },
  mounted() {
    this.init();
    this.repaintConnetion();
    // 每次页面大小改变重新绘画连线
    window.addEventListener("resize", this.repaintPlumb);
  },
};
</script>
<style lang="less" scoped>
::-webkit-scrollbar {
  width: 0.2vw;
  background-color: rgba(192, 192, 192, 0);
}

.diy_overlay {
  width: 3vw;
  background-color: red;
  height: 3vw;
}

// #plumbContent {
//   position: relative;
// }
.content {
  display: flex;
  justify-content: space-around;
  user-select: none;
  padding: 3vw;
  position: relative;
  overflow: scroll;
  // height: 28vw;
}

.right,
.left {
  // padding-right: 1vw;
  color: #fff;
  width: 30%;
  position: relative;
  text-align: center;
  .top {
    border: none;
    font-size: 0.8vw;
    font-weight: 600;
    color: #fff;
  }

  .bottom {
    position: relative;
    height: 25vw;
    overflow-y: scroll;
    padding-right: 2vw;
    border: 1px #fff solid;
    margin: 0 auto;
    width: 80%;
    margin-top: 0.5vw;
    li {
      list-style: none;
      display: inline-block;
      margin-top: 1vw;
      width: 100%;
      cursor: pointer;
      min-width: 5vw;
      text-align: center;
      border: 1px #fff solid;
    }
  }
}
.right {
  width: 60%;
  .bottom {
    li {
      color: #fff;
      border: 1px #fff solid;
      padding: 1vw 0;
      div {
        border: 1px #fff solid;
        border-radius: 3px;
        display: inline-block;
        margin-left: 0.5vw;
        padding: 0 0.2vw;
      }
    }
  }
}

.endpointLabel {
  color: red;
  font-size: 0.5vw;
  font-weight: 600;
  cursor: pointer;
}
</style>

Logo

前往低代码交流专区

更多推荐