当前位置:首页 > VUE

vue实现节点连线

2026-01-17 05:37:43VUE

Vue 实现节点连线的方法

使用 SVG 和动态计算

在 Vue 中可以通过 SVG 实现节点间的连线。SVG 的 <path><line> 元素可用于绘制连接线,动态计算节点位置并更新连线路径。

<template>
  <svg width="100%" height="500">
    <!-- 节点 -->
    <circle 
      v-for="(node, index) in nodes" 
      :key="index" 
      :cx="node.x" 
      :cy="node.y" 
      r="20" 
      fill="blue"
      @mousedown="startDrag(index, $event)"
      @mousemove="dragNode($event)"
      @mouseup="stopDrag"
    />
    <!-- 连线 -->
    <path 
      v-for="(link, index) in links" 
      :key="'link-' + index" 
      :d="calculatePath(link)" 
      stroke="black" 
      fill="none"
    />
  </svg>
</template>

<script>
export default {
  data() {
    return {
      nodes: [
        { x: 100, y: 100 },
        { x: 300, y: 200 }
      ],
      links: [
        { source: 0, target: 1 }
      ],
      dragging: null
    };
  },
  methods: {
    calculatePath(link) {
      const source = this.nodes[link.source];
      const target = this.nodes[link.target];
      return `M ${source.x} ${source.y} L ${target.x} ${target.y}`;
    },
    startDrag(index, event) {
      this.dragging = index;
    },
    dragNode(event) {
      if (this.dragging !== null) {
        const rect = event.target.getBoundingClientRect();
        this.nodes[this.dragging].x = event.clientX - rect.left;
        this.nodes[this.dragging].y = event.clientY - rect.top;
      }
    },
    stopDrag() {
      this.dragging = null;
    }
  }
};
</script>

使用第三方库(jsPlumb)

jsPlumb 是一个专门用于实现节点连线的库,支持拖拽、连线样式自定义等功能。

vue实现节点连线

安装 jsPlumb:

vue实现节点连线

npm install jsplumb

在 Vue 中使用:

<template>
  <div class="container">
    <div 
      v-for="(node, index) in nodes" 
      :key="index" 
      :id="'node-' + index" 
      class="node"
    >
      Node {{ index }}
    </div>
  </div>
</template>

<script>
import { jsPlumb } from 'jsplumb';

export default {
  mounted() {
    this.initJsPlumb();
  },
  data() {
    return {
      nodes: [ {}, {} ]
    };
  },
  methods: {
    initJsPlumb() {
      jsPlumb.ready(() => {
        jsPlumb.connect({
          source: 'node-0',
          target: 'node-1',
          anchors: ['Right', 'Left'],
          connector: ['Straight'],
          endpoint: 'Blank'
        });
      });
    }
  }
};
</script>

<style>
.container {
  position: relative;
  height: 500px;
}
.node {
  position: absolute;
  width: 100px;
  height: 50px;
  border: 1px solid #ccc;
  padding: 10px;
}
#node-0 { left: 50px; top: 100px; }
#node-1 { left: 300px; top: 200px; }
</style>

使用 Canvas 和动态渲染

通过 Canvas 可以实现高性能的节点连线,适合大量节点的场景。

<template>
  <canvas ref="canvas" width="800" height="500" @mousedown="handleMouseDown"></canvas>
</template>

<script>
export default {
  data() {
    return {
      nodes: [
        { x: 100, y: 100 },
        { x: 300, y: 200 }
      ],
      links: [
        { source: 0, target: 1 }
      ],
      selectedNode: null
    };
  },
  mounted() {
    this.drawCanvas();
  },
  methods: {
    drawCanvas() {
      const canvas = this.$refs.canvas;
      const ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 绘制连线
      ctx.strokeStyle = 'black';
      this.links.forEach(link => {
        const source = this.nodes[link.source];
        const target = this.nodes[link.target];
        ctx.beginPath();
        ctx.moveTo(source.x, source.y);
        ctx.lineTo(target.x, target.y);
        ctx.stroke();
      });

      // 绘制节点
      ctx.fillStyle = 'blue';
      this.nodes.forEach(node => {
        ctx.beginPath();
        ctx.arc(node.x, node.y, 20, 0, Math.PI * 2);
        ctx.fill();
      });
    },
    handleMouseDown(event) {
      const rect = this.$refs.canvas.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;

      this.nodes.forEach((node, index) => {
        const distance = Math.sqrt((x - node.x)  2 + (y - node.y)  2);
        if (distance <= 20) {
          this.selectedNode = index;
          document.addEventListener('mousemove', this.handleMouseMove);
          document.addEventListener('mouseup', this.handleMouseUp);
        }
      });
    },
    handleMouseMove(event) {
      if (this.selectedNode !== null) {
        const rect = this.$refs.canvas.getBoundingClientRect();
        this.nodes[this.selectedNode].x = event.clientX - rect.left;
        this.nodes[this.selectedNode].y = event.clientY - rect.top;
        this.drawCanvas();
      }
    },
    handleMouseUp() {
      this.selectedNode = null;
      document.removeEventListener('mousemove', this.handleMouseMove);
      document.removeEventListener('mouseup', this.handleMouseUp);
    }
  }
};
</script>

注意事项

  • 动态计算连线路径时,需考虑节点的位置变化,实时更新连线。
  • 使用第三方库(如 jsPlumb)时,注意在组件销毁时清理资源。
  • Canvas 方案需手动处理交互和渲染,适合复杂场景。

标签: 节点vue
分享给朋友:

相关文章

vue怎么实现数据检测

vue怎么实现数据检测

Vue 数据检测的实现方式 Vue 通过响应式系统实现数据检测,核心机制基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)。以下是具体实现方法: 基于 Vue…

vue实现安全免登录

vue实现安全免登录

Vue 实现安全免登录的方案 免登录功能通常通过持久化认证状态(如 Token)实现,但需兼顾安全性。以下是基于 Vue 的常见实现方案: 基于 Token 的免登录 登录成功后存储 Toke…

vue实现点击旋转轮盘

vue实现点击旋转轮盘

实现点击旋转轮盘效果 在Vue中实现点击旋转轮盘效果,可以通过CSS动画和Vue的数据绑定结合完成。以下是一个完整的实现方案: 准备工作 需要安装Vue.js环境,可以通过CDN引入或使用Vue C…

vue实现用户信息删除

vue实现用户信息删除

Vue 实现用户信息删除功能 在 Vue 中实现用户信息删除功能通常涉及前端界面交互和后端 API 调用。以下是实现步骤: 前端界面设计 创建删除按钮或操作项,通常使用 @click 事件触发删除操…

vue实现轮询

vue实现轮询

实现轮询的基本方法 在Vue中实现轮询可以通过setInterval或setTimeout配合递归调用完成。轮询通常用于定期向服务器请求数据更新。 使用setInterval的简单示例: da…

vue实现弹窗

vue实现弹窗

Vue 实现弹窗的常见方法 使用组件化方式封装弹窗 创建一个独立的弹窗组件(如 Modal.vue),通过 v-if 或 v-show 控制显示隐藏: <template> <…