Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何解决连线超出容器的范围呢? #51

Open
taoyameng opened this issue Dec 9, 2024 · 2 comments
Open

如何解决连线超出容器的范围呢? #51

taoyameng opened this issue Dec 9, 2024 · 2 comments

Comments

@taoyameng
Copy link

image
image
我需要将两个表格的行进行连线映射,目前实现了连线,但是如果表格带有滚动条的时候,连线就会出现这个情况,请问有没有什么办法解决呢?

@MonsterGoGoGo
Copy link

MonsterGoGoGo commented Dec 9, 2024 via email

@taoyameng
Copy link
Author

taoyameng commented Dec 9, 2024

这是我的代码

<template>
  <div id="container"
       style="width: 100%;	position: relative; display: flex; justify-content: space-around;  height: 300px;">
<!--        <el-table-->
<!--          ref="leftTable"-->
<!--          :data="leftTreeData"-->
<!--          style="width: 30%; margin-bottom: 20px; display: inline-block; overflow-y: auto;position: relative;"-->
<!--          row-key="id"-->
<!--          height="350"-->
<!--          :row-class-name="({row}) => `leftRow Id-${row.id}`"-->
<!--          border-->
<!--        >-->
<!--          <el-table-column prop="name" label="姓名"/>-->
<!--          <el-table-column prop="gender" label="性别"/>-->
<!--          <el-table-column prop="age" label="年龄"/>-->
<!--        </el-table>-->
<!--        <el-table-->
<!--          ref="rightTable"-->
<!--          :data="rightTreeData"-->
<!--          :row-class-name="({row}) => `rightRow Id-${row.id}`"-->
<!--          style="width: 30%; margin-bottom: 20px; margin-left: 300px; display: inline-block;"-->
<!--          row-key="id"-->
<!--          border-->
<!--        >-->
<!--          <el-table-column prop="name" label="姓名"/>-->
<!--          <el-table-column prop="gender" label="性别"/>-->
<!--          <el-table-column prop="age" label="年龄"/>-->
<!--        </el-table>-->

    <table border="1" width="400" cellspacing="0" height="300">
      <thead>
      <tr>
        <th>姓名</th>
        <th>性别</th>
        <th>年龄</th>
      </tr>
      </thead>
      <tbody>
      <tr v-for="(item,index) in leftTreeData" :class="`leftRow Id-${item.id}`" :id="`leftRow-id-${item.id}`">
        <td>{{ item.name }}</td>
        <td>{{ item.gender }}</td>
        <td>{{ item.age }}</td>
      </tr>
      </tbody>
    </table>


    <table border="1" width="400" cellspacing="0" height="300">
      <thead>
      <tr>
        <th>姓名</th>
        <th>性别</th>
        <th>年龄</th>
      </tr>
      </thead>
      <tbody>
      <tr v-for="(item,index) in rightTreeData" :class="`rightRow Id-${item.id}`" :id="`rightRow-id-${item.id}`">
        <td>{{ item.name }}</td>
        <td>{{ item.gender }}</td>
        <td>{{ item.age }}</td>
      </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import {jsPlumb} from 'jsplumb'

let instance = null;

export default {
  name: "JsPlumb",
  data() {
    return {
      leftTreeData: [
        {id: "1", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "2", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false},
        {id: "3", name: '坤坤', gender: '女', age: 24, parentId: null, hasChild: false},
        {id: "4", name: '小黑子', gender: '男', age: 25, parentId: null, hasChild: false},
        {id: "5", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "6", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false},
        {id: "7", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "8", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false},
        {id: "9", name: '坤坤', gender: '女', age: 24, parentId: null, hasChild: false},
        {id: "10", name: '小黑子', gender: '男', age: 25, parentId: null, hasChild: false},
        {id: "11", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "12", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false}
      ],
      rightTreeData: [
        {id: "1", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "2", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false},
        {id: "3", name: '坤坤', gender: '女', age: 24, parentId: null, hasChild: false},
        {id: "4", name: '小黑子', gender: '男', age: 25, parentId: null, hasChild: false},
        {id: "5", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "6", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false},
        {id: "7", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "8", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false},
        {id: "9", name: '坤坤', gender: '女', age: 24, parentId: null, hasChild: false},
        {id: "10", name: '小黑子', gender: '男', age: 25, parentId: null, hasChild: false},
        {id: "11", name: '张三', gender: '男', age: 23, parentId: null, hasChild: false},
        {id: "12", name: '李四', gender: '男', age: 22, parentId: null, hasChild: false}
      ]
    };
  },
  methods: {

    initJsPlumb() {
      const _this = this;
      jsPlumb.ready(function () {
        // 初始化jsPlumb 创建jsPlumb实例
        _this.init();
        // 设置可以为连线起点和连线终点的元素
        _this.setContainer();
        // 设置默认连线
        const relationship = [
          {sourceId: "1", targetId: "2"},
          {sourceId: "2", targetId: "3"},
          {sourceId: "3", targetId: "4"},
        ];
        _this.setConnect(relationship);
        // 绑定事件监听
        _this.setEvent();
      });
    },


    setContainer() {
      const leftElList = document.querySelectorAll('.leftRow'); // 左侧行元素集合
      const rightElList = document.querySelectorAll('.rightRow');  // 右侧行元素集合
      // 将dom元素设置为连线的起点或者终点 设置了起点的元素才能开始连线 设置为终点的元素才能为连线终点
      const _this = this
      instance.batch(function () {
        [leftElList, rightElList].forEach((trList, index) => {
          trList.forEach((tr) => {
            const id = _this.interceptId(tr.classList[1]);
            if (index === 0) {
              const item = _this.leftTreeData.find(i => i.id == id);
              // 判断是否有子项,若没有则设置为起点
              !item?.hasChild && instance.makeSource(tr, {
                allowLoopback: false,
                anchor: ["Right"], // 设置端点位置
                maxConnections: 1
              });
            } else {
              const item = _this.rightTreeData.find(i => i.id == id);
              // 判断是否有子项,若没有则设置为终点
              !item?.hasChild && instance.makeTarget(tr, {
                anchor: ["Left"],
                maxConnections: 1
              });
            }
          });
        });
      });
    },

    //  绑定事件监听
    setEvent() {
      // 连线事件
      instance.bind("connection", function (connInfo, originalEvent) {
        // connInfo是jsPlumb对象 可以打印出来康康有哪些东西
        console.log(connInfo, originalEvent, 'connInfo')
      });

      // 点击连接线删除该条线
      instance.bind("click", (conn, originalEvent) => {
        this.$confirm("确认删除映射么?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          closeOnClickModal: false,
          type: "warning",
        })
          .then(() => {
            instance.deleteConnection(conn);
          })
          .catch(() => {
          });
      });
    },

    // 截取元素类名中的id
    interceptId(className) {
      return className.slice(className.indexOf('-') + 1);
    },

    //始化
    init() {
      instance = jsPlumb.getInstance({
        Connector: "Straight", //连接线形状 Bezier: 贝塞尔曲线 Flowchart: 具有90度转折点的流程线 StateMachine: 状态机 Straight: 直线
        PaintStyle: {strokeWidth: 2, stroke: "#4e6ef2"}, //连接线样式
        Endpoint: ["Blank", {radius: 1}], //端点
        anchor: 'Right',
        HoverPaintStyle: {stroke: "#000000"}, // 默认悬停样式  默认为null
        // 绘制箭头
        Overlays: [['Arrow', {width: 8, length: 8, location: 1}]],
        EndpointStyle: {fill: "#000000"}, //端点样式
        Container: "container", //目标容器id
        ListStyle: {
          endpoint: ["Rectangle", {width: 30, height: 30}],
        },
      });
    },

    /**
     * 设置默认连线
     * @param relationship
     */
    setConnect(relationship) {
      setTimeout(() => {
        relationship.forEach(function (data) {
          // source是连线起点元素id target是连线终点元素id
          // instance.connect({
          //   source: document.querySelector(`.leftRow.Id-${data.sourceId}`),
          //   target: document.querySelector(`.rightRow.Id-${data.targetId}`)
          // });
          instance.connect({
            source: "leftRow-id-" + data.sourceId,
            target: "rightRow-id-" + data.targetId
          });
        });
      }, 100)
    }
  },
  mounted() {
    this.initJsPlumb();
    // 假设这是你的表格容器
    //document.querySelector('.el-table .el-table__body-wrapper')
    document.querySelectorAll('table').forEach(item => {
      item.addEventListener('scroll', function () {
        //instance.repaintEverything();

        let connections = instance.getAllConnections();
        connections.forEach(item => {
          console.log(item.source, '-----------', item.target)
        })
        let linePoints = [];
        for (let i = connections.length - 1; i >= 0; i--) {
          linePoints.push([connections[i].sourceId, connections[i].targetId]);
          instance.deleteConnection(connections[i]);
        }
        for (let i = 0; i < linePoints.length; i++) {
          instance.connect({
            source: linePoints[i][0],
            target: linePoints[i][1]
          });
        }
      })
    })
  }
}
</script>

<style scoped>
td, th {
  height: 50px;
  width: 100px;
}

table {
  display: block;
  overflow-y: auto;
}
</style>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants