当前位置:首页 > 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中实现右下角弹框,通常需要结合CSS定位和Vue的组件化特性。弹框可以通过绝对定位固定在右下角,并通过Vue控制其显示与隐藏。 创建弹框组件 新建一个Vue组件(如…

vue实现标签

vue实现标签

Vue 实现标签的方法 在 Vue 中实现标签功能可以通过多种方式完成,以下是几种常见的方法: 使用动态组件 动态组件可以根据不同的条件渲染不同的标签内容。通过 :is 属性动态绑定组件名,实现标签…

jquery实现vue

jquery实现vue

jQuery 和 Vue.js 是两种不同理念的前端工具,jQuery 以 DOM 操作和事件驱动为核心,而 Vue.js 是数据驱动的现代化框架。如果想用 jQuery 实现类似 Vue 的功能(如…

vue模版实现

vue模版实现

Vue 模板实现方法 Vue 模板是 Vue.js 的核心特性之一,用于声明式地将 DOM 绑定至底层 Vue 实例的数据。以下是几种常见的 Vue 模板实现方式: 单文件组件(SFC) 使用 .v…

vue递归实现

vue递归实现

vue递归实现方法 在Vue中实现递归组件通常用于树形结构、嵌套菜单等场景。以下是具体实现方式: 使用组件name属性递归 定义一个组件时,通过name属性让组件可以在自身模板中调用自己:…

vue实现图片查看

vue实现图片查看

Vue 实现图片查看功能 在 Vue 中实现图片查看功能,可以通过原生实现或使用第三方库。以下是几种常见的方法: 原生实现方式 使用 Vue 的指令和事件绑定实现基础的图片查看功能。 <te…