You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KonvaJS:如何实现多可拖拽图形的连线同步联动?

Fixing Konva.js Draggable Boxes with Synchronized Lines

Hey there! Let's sort out that issue where your lines don't move along with the draggable boxes. The main problems in your current code are:

  1. You're creating duplicate boxes for child elements (since boxes already includes box2 and box3, but your loop draws them again when processing box_1's children)
  2. Lines are only using the initial position of boxes—there's no logic to update their points when a box is dragged.

Here's a scalable solution that works for any number of boxes and connections:

Step 1: Refactor Your Data Structure

First, let's separate box data from their connections so we can track links clearly:

// Define your boxes with unique IDs
let box_1 = {id: 'box1', x:20, y:20, width:150, height:100, color:'red'};
let box2 = {id: 'box2', x:500, y:20, width:150, height:100, color:'green'};
let box3 = {id: 'box3', x:300, y:300, width:150, height:100, color:'blue'};
let boxes = [box_1, box2, box3];

// Track connections separately (each entry links two box IDs)
let connections = [
  {from: 'box1', to: 'box2'},
  {from: 'box1', to: 'box3'}
];

Step 2: Draw Boxes (No Duplicates!)

We'll draw each box once, and store a reference to the Konva Rect object in our box data for easy access later:

function drawBoxes(listOfBoxes) {
  for (let boxData of listOfBoxes) {
    const boxShape = new Konva.Rect({
      id: boxData.id,
      x: boxData.x,
      y: boxData.y,
      width: boxData.width,
      height: boxData.height,
      fill: boxData.color,
      stroke: 'black',
      strokeWidth: 4,
      draggable: true
    });
    // Save the Konva shape reference
    boxData.shape = boxShape;
    layer.add(boxShape);
  }
}

Step 3: Draw Lines with Drag Sync Logic

We need two helper functions: one to fetch a box by ID, and another to update a line's position based on its connected boxes. We'll bind the update function to the dragmove event of each box so lines move in real-time.

// Helper to get a box by its ID
function getBoxById(id) {
  return boxes.find(box => box.id === id);
}

// Update line points to match current box positions
function updateLine(line, fromBox, toBox) {
  // Optional: connect centers of boxes (adjust to edges if needed)
  const fromCenterX = fromBox.shape.getX() + fromBox.width / 2;
  const fromCenterY = fromBox.shape.getY() + fromBox.height / 2;
  const toCenterX = toBox.shape.getX() + toBox.width / 2;
  const toCenterY = toBox.shape.getY() + toBox.height / 2;

  line.points([fromCenterX, fromCenterY, toCenterX, toCenterY]);
  layer.draw(); // Refresh the layer to show changes
}

// Draw all connections and bind drag events
function drawConnections(connectionList) {
  for (let conn of connectionList) {
    const fromBox = getBoxById(conn.from);
    const toBox = getBoxById(conn.to);

    const line = new Konva.Line({
      stroke: 'black',
      strokeWidth: 5,
      lineCap: 'round',
      lineJoin: 'round'
    });

    // Store references to connected boxes in the line
    line.fromBox = fromBox;
    line.toBox = toBox;

    // Set initial line position
    updateLine(line, fromBox, toBox);
    layer.add(line);

    // Update line when either connected box is dragged
    fromBox.shape.on('dragmove', () => updateLine(line, fromBox, toBox));
    toBox.shape.on('dragmove', () => updateLine(line, fromBox, toBox));
  }
}

Step 4: Assemble Everything

Put it all together with your stage setup:

var stage = new Konva.Stage({
  container: 'container',
  width: 600,
  height: 800
});
var layer = new Konva.Layer();

drawBoxes(boxes);
drawConnections(connections);

stage.add(layer);

What This Fixes:

  • No More Duplicate Boxes: Each box is drawn exactly once from the boxes array.
  • Real-Time Line Updates: Every time you drag a box, all lines connected to it update their position instantly.
  • Scalable: Add more boxes and connections just by adding entries to the boxes and connections arrays—no need to rewrite core logic.
  • Adjustable Line Placement: If you prefer lines to connect edges instead of centers, modify the updateLine function (e.g., use fromBox.shape.getX() + fromBox.width for the right edge of the source box).

内容的提问来源于stack exchange,提问作者azlan_909

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:56:00