vue3 jsPlumb学习

<template>
  <div class="box">
    <div @click="clearLine">clear</div>
    <div @click="initConponents">line</div>
    <div @click="getData">get</div>
  </div>
  <div class="wrapper" ref="wrapper">
    <div class="left_box com_box">
      <div class="source_title com_title">{{ props.sourceTitle }}</div>
      <div class="content_box" id="content_box1">
        <div
          class="item_box"
          :id="item.id"
          v-for="(item, index) in sourceList"
          :key="`item-${index}`"
        >
          {{ item.name }}
        </div>
      </div>
    </div>
    <div class="right_box com_box">
      <div class="target_title com_title">{{ props.targetTitle }}</div>
      <div class="content_box" id="content_box2">
        <div
          class="item_box"
          :id="item.id"
          v-for="(item, index) in targetList"
          :key="`item-${index}`"
        >
          {{ item.name }}
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { jsPlumb } from 'jsplumb'
const props = defineProps({
  targetTitle: {
    type: String,
    default: '目标字段'
  },
  sourceTitle: {
    type: String,
    default: '源字段'
  }
})
const wrapper = ref()
// 公共样式  点样式和连线样式
const commonData = {
  isSource: true, // 是否允许被手动连线
  isTarget: true, // 是否允许被手动连线
  connectorStyle: { stroke: '#5085E2', strokeWidth: '2', dashstyle: '0' }, // 自定义连线时的颜色
  connectorHoverStyle: {
    lineWidth: 3,
    strokeStyle: '#ff3040',
    stroke: '#ff3040'
  }, // 自定义线段连接后 鼠标经过的颜色 宽度
  connectorOverlays: [['Arrow', { width: 10, length: 10, location: 1 }]], // 自定义连线时箭头的样式
  connector: ['Bezier', { curviness: 50 }], // 连线样式
  anchor: ['Left', 'Right'], // 点的位置
  endpointStyle: { fill: '#5085E2', outlineWidth: 2 }, // 点的样式
  endpointHoverStyle: { fill: '#ff3040', outlineWidth: 2 }, // 初始化连接时鼠标经过时点的样式
  paintStyle: { stroke: '#5085E2', strokeWidth: 2 }, // 初始化连接时连线的颜色 宽度
  hoverPaintStyle: { stroke: '#ff3040', strokeWidth: 2 }, // 初始化连接时鼠标经过时的连线颜色 宽度
  overlays: [['Arrow', { width: 10, length: 10, location: 1 }]], // 初始化连接时箭头样式 location 0.5 箭头在中间 1在右侧
  endpoint: [
    'Dot',
    {
      radius: 5, // 圆的大小
      fill: '#5085E2'
    }
  ], // 端点样式设置
  DragOptions: { cursor: 'crosshair' },
  ConnectionsDetachable: false // 禁用拖到取消连线
}
const sourceList = ref([])
const targetList = ref([])
const initConponents = () => {
  // 通过index (同行)
  const source = sourceList.value.map((item) => item.id)
  const target = targetList.value.map((item) => item.id)
  // 通过uuid连接(自定义)
  // const source = sourceList.value.map((item) => item.uuid)
  // const target = targetList.value.map((item) => item.uuid)
  source.forEach((item, index) => {
    // 连线
    jsPlumb.connect({ uuids: [item, target[index]] }, commonData)
  })
}
const clearLine = () => {
  const doms = document.querySelectorAll('.item_box')
  doms.forEach((item) => {
    // 根据id删除点的连线
    jsPlumb.deleteConnectionsForElement(item.id)
  })
}
const getData = () => {
  // 获取全部连接线段的数据,通过id去list中查找,处理成接口想要的数据格式
  console.log(jsPlumb.getAllConnections())
}
onMounted(() => {
  jsPlumb.getInstance()
  const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  list.forEach((item, index) => {
    targetList.value.push({
      name: `target-${item}`, // 展示字段
      id: `target-${index}`, // id
      uuid: `target-${item}` // 动态设置连接的id
    })
    sourceList.value.push({
      name: `source-${item}`,
      id: `source-${index}`,
      uuid: `source-${item}`
    })
  })
  nextTick(() => {
    sourceList.value.forEach((item) => {
      const dom = document.querySelector(`#${item.id}`)
      // addEndpoint 添加右侧点位
      jsPlumb.addEndpoint(
        dom,
        {
          anchor: ['Right'],
          uuid: item.id // 如果是同行连接 uuid: item.id  如果是uuid  uuid: item.uuid  注意 需要和initConponents map条件一致
        },
        // 点的样式
        { ...commonData, maxConnections: 1 }
      )
    })
    targetList.value.forEach((item) => {
      const dom = document.querySelector(`#${item.id}`)
      // addEndpoint 添加左侧点位
      jsPlumb.addEndpoint(
        dom,
        {
          anchor: ['Left'],
          uuid: item.id // 如果是同行连接 uuid: item.id  如果是uuid  uuid: item.uuid 注意 需要和initConponents map条件一致
        },
        // 点的样式
        { ...commonData, maxConnections: 1 }
      )
    })
  })

  // 添加单击连线事件
  // jsPlumb.bind('click', function (conn) {
  //   // 删除线
  //   jsPlumb.deleteConnection(conn)
  // })

  // 鼠标经过线的样式
  jsPlumb.bind('mouseover', function (conn) {
    for (let i of document.querySelectorAll('.jtk-connector')) {
      i.style.cursor = conn.targetId === 'r_dataDictionary' ? 'default' : 'pointer'
    }
  })

  // 鼠标离开线的样式
  jsPlumb.bind('mouseout', function (conn) {
    for (let i of document.querySelectorAll('.jtk-connector')) {
      i.style.cursor = conn.targetId === 'r_dataDictionary' ? 'default' : 'pointer'
    }
  })

  // 连线之前,是否可连接检查
  jsPlumb.bind('beforeDrop', function (info) {
    // return false 不允许连接  true 允许连接
    const sourceId = info.sourceId.split('-')[0]
    const targetId = info.targetId.split('-')[0]
    // 不允许连接同一侧的点 或者 不允许从右侧拉线到左侧   只能从左到右拉线
    if (sourceId === targetId || sourceId.includes('target')) return false
    return true
  })

  // 连线成功之后的回调
  // jsPlumb.bind('connection', function (info) {
  //   console.log(info.connection, 9, info)
  // })
})
</script>
<style lang="less" scoped>
.box {
  display: flex;
  width: 500px;
  justify-content: space-between;
  align-items: center;
  margin: 50px auto;
}
.wrapper {
  width: 1000px;
  height: 500px;
  margin: 200px auto 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  .com_box {
    width: 30%;
    height: 100%;
    border: 1px solid #ccc;
    display: flex;
    flex-direction: column;
  }
  .com_title {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    height: 30px;
    line-height: 30px;
    margin-bottom: 10px;
    color: #fff;
    background-color: #ccc;
  }
  .content_box {
    height: 0;
    flex: 1;
    width: 100%;
    overflow: auto;
    display: flex;
    flex-direction: column;
    padding: 0 10px;
    box-sizing: border-box;
    > div {
      height: 20px;
      line-height: 19px;
      border-bottom: 1px solid #ccc;
      color: #ccc;
      white-space: nowrap; /* 不换行 */
      overflow: hidden; /* 超出部分不显示 */
      text-overflow: ellipsis; /* 超出部分显示为... */
      border: 1px solid #ccc;
      border-bottom: none;
      padding: 0 8px;
      box-sizing: border-box;
      &:last-child {
        border-bottom: 1px solid #ccc;
      }
    }
  }
}
</style>
posted @ 2023-11-27 17:59  Life_countdown  阅读(292)  评论(0编辑  收藏  举报