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

SwiftUI中如何让线条跟随CGPoint拖拽移动?

SwiftUI拖拽节点时线条同步跟随移动的实现方案

我在SwiftUI中创建了两个可拖拽的节点(CGPoint),并绘制了连接它们的线条。需求是拖拽第二个节点时,线条能同步跟随其移动,保持连接状态,但目前线条并未随拖拽动作移动,请问该如何修复?


原代码

Point.swift

import SwiftUI

struct Point : View {
    var position: CGPoint

    init(_ position: CGPoint) {
        self.position = position
    }
    var body: some View {
        Circle()
            .frame(width: 20)
            .foregroundColor(.white)
            .position(x: position.x, y: position.y)
    }
}

LineWithPoints.swift

struct LineWithPoints : View {
    @State var point1 = Point(.init(x: 0,   y: 0))
    @State var point2 = Point(.init(x: 450, y: 0))
    @State private var offset1 = CGSize.zero
    
    var body: some View {
        let lineBetween = LineBetween(pointPosition: $point2.position)
        
        ZStack {
            lineBetween.stroke(.red, lineWidth: 2)
            point1;               
            point2
                .offset(x: offset1.width, y: offset1.height)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            let x = value.startLocation.x
                            let y = value.startLocation.y
                            let w = value.translation.width
                            let h = value.translation.height
                            offset1 = .init(width: (x + w) - point2.position.x,
                                           height: (y + h) - point2.position.y)
                        }
                )
        }
    }
    struct LineBetween : Shape, @unchecked Sendable {
        @Binding var pointPosition: CGPoint

        func path(in rect: CGRect) -> Path {
            var path = Path()
            path.move(to: CGPoint.zero)
            path.addLine(to: pointPosition)
            path.closeSubpath()
            return path
        }
    }
}

ContentView.swift

struct ContentView : View {
    var body: some View {
        ZStack {
            Color.black.ignoresSafeArea()
            LineWithPoints()
        }
    }
}

问题原因

原代码的核心问题:

  • 使用offset移动point2时,并未更新point2自身的position属性,导致绑定给LineBetween的pointPosition值无变化,线条无法更新。
  • LineBetween的路径起点固定为CGPoint.zero,但point1的实际位置可能并非原点,导致线条起点错误。

修复方案

1. 修改Point视图,支持双向绑定

将Point的position改为@Binding,让父视图能直接修改它的位置:

import SwiftUI

struct Point : View {
    @Binding var position: CGPoint

    init(_ position: Binding<CGPoint>) {
        self._position = position
    }
    var body: some View {
        Circle()
            .frame(width: 20)
            .foregroundColor(.white)
            .position(x: position.x, y: position.y)
    }
}

2. 重构LineWithPoints视图,直接更新节点位置

移除offset1变量,拖拽时直接修改point2的坐标,同时让LineBetween连接两个节点的实际位置:

struct LineWithPoints : View {
    @State private var point1Pos = CGPoint(x: 0, y: 0)
    @State private var point2Pos = CGPoint(x: 450, y: 0)
    
    var body: some View {
        ZStack {
            LineBetween(from: point1Pos, to: point2Pos)
                .stroke(.red, lineWidth: 2)
            
            Point($point1Pos)
            Point($point2Pos)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            // 直接将point2的位置更新为拖拽实时位置
                            point2Pos = value.location
                        }
                )
        }
    }
    
    struct LineBetween : Shape, @unchecked Sendable {
        let from: CGPoint
        let to: CGPoint

        func path(in rect: CGRect) -> Path {
            var path = Path()
            path.move(to: from)
            path.addLine(to: to)
            return path
        }
    }
}

3. ContentView保持不变

struct ContentView : View {
    var body: some View {
        ZStack {
            Color.black.ignoresSafeArea()
            LineWithPoints()
        }
    }
}

说明

  • 拖拽时直接修改point2Pos的坐标,SwiftUI会自动触发视图更新,LineBetween会使用最新的两点坐标重新绘制线条。
  • 将Point的position改为@Binding,确保父视图的状态变化能同步到子视图。
  • LineBetween现在直接接收两个节点的坐标,绘制逻辑更清晰,避免了原点依赖问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:53:13