当前位置:首页 > 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实现visual

vue实现visual

Vue 实现可视化(Visual)的常见方法 在 Vue 中实现可视化通常涉及数据可视化库的集成,以下是几种主流方案: 使用 ECharts ECharts 是一个强大的 JavaScript 图表…

vue SSG实现

vue SSG实现

Vue SSG 实现方法 Vue 的静态站点生成(SSG)可以通过多种工具和框架实现,以下是几种常见的方法: 使用 VuePress VuePress 是一个基于 Vue 的静态站点生成器,适合文档…

vue实现markdown

vue实现markdown

Vue 实现 Markdown 编辑器 在 Vue 中实现 Markdown 编辑器可以通过集成第三方库或自定义解析器完成。以下是两种常见方法: 使用第三方库(如 marked 或 markdown…

vue实现节流

vue实现节流

vue实现节流的方法 在Vue中实现节流(throttle)功能,通常用于限制高频事件的触发频率,例如滚动、输入或按钮点击。以下是几种常见的实现方式: 使用Lodash的throttle函数 安装L…

vue 实现脚本

vue 实现脚本

Vue 实现脚本的方法 Vue.js 提供了多种方式来实现脚本功能,包括组件内脚本、混入(Mixins)、插件(Plugins)以及自定义指令等。以下是常见的实现方式: 组件内脚本 在 Vue 单文…