当前位置:首页 > 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 是一个专门用于实现节点连线的库,支持拖拽、连线样式自定义等功能。

安装 jsPlumb:

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 卖座网实现 项目结构搭建 使用 Vue CLI 快速初始化项目,安装必要依赖如 Vue Router、Vuex、Axios。 创建核心目录结构:components(通用组件)、views(页…

vue实现压缩上传文件

vue实现压缩上传文件

压缩上传文件的实现方法 在Vue中实现文件压缩和上传功能,可以通过以下步骤完成。该方法结合了前端文件压缩库和HTTP请求,确保文件在上传前被有效压缩。 安装必要的依赖 需要使用compressorj…

在线脑图 vue 实现

在线脑图 vue 实现

在线脑图 Vue 实现方案 使用开源库实现 推荐使用 mind-elixir 或 jsmind 这类开源库,它们专为脑图设计且支持 Vue 集成。 安装依赖: npm install mind…

vue设计与实现 书

vue设计与实现 书

vue设计与实现 书 《Vue.js设计与实现》是一本深入探讨Vue.js框架内部原理和设计思想的书籍,适合希望深入理解Vue.js的开发者。以下是关于这本书的详细信息: 书籍内容 《Vue…

vue手写签名如何实现

vue手写签名如何实现

实现手写签名的基本思路 在Vue中实现手写签名功能,通常需要借助HTML5的Canvas API来捕获用户的绘制操作。核心流程包括初始化画布、监听触摸/鼠标事件、记录轨迹以及生成签名图片。…

vue状态管理怎么实现

vue状态管理怎么实现

Vue 状态管理实现方法 使用 Vuex(官方推荐) Vuex 是 Vue 的官方状态管理库,适合中大型应用。 安装 Vuex: npm install vuex --save 创建 Store 示…