我创建了两个 CGPoint 以及它们之间的连接线。我的目标如下:当我使用 SwiftUI DragGesture() 拖动第二个 CGPoint 时,线条将跟随它(就像它已连接到它一样)。目前这条线不跟随点。 我该怎么做?
这是我的代码:
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()
}
}
}
在您的 DragGesture 中,您没有更改传递给 LineBetween 的 pointPosition ,您只更改第二个圆的偏移量。您可以为第二个圆的偏移量和形状端点创建相同的变量
以下是一些需要纠正的事情:
LineBetween
只接受一个点作为参数,它假设另一点位于(0,0)。Binding
,因为该点是只读的。ZStack
外部创建形状,然后在堆栈内描画它,不如在一次操作中创建它并在 ZStack
内部描画它会更好。这是解决上述问题的修订版本。它将线绘制到目标点。这是一个单独的状态变量,反映点 2 的最新位置。目标点在拖动过程中更新。
struct LineWithPoints : View {
@State private var point1: Point
@State private var point2: Point
@State private var offset = CGSize()
@State var targetPoint: CGPoint
init(
point1: CGPoint = CGPoint(x: 50, y: 200),
point2: CGPoint = CGPoint(x: 325, y: 200)
) {
self._point1 = State(initialValue: Point(point1))
self._point2 = State(initialValue: Point(point2))
self._targetPoint = State(initialValue: point2)
}
struct LineBetween : Shape {
let point1: CGPoint
let point2: CGPoint
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: point1)
path.addLine(to: point2)
path.closeSubpath()
return path
}
}
var body: some View {
ZStack {
LineBetween(
point1: point1.position,
point2: targetPoint
)
.stroke(.red, lineWidth: 2)
point1
point2
.offset(x: offset.width, y: offset.height)
.gesture(
DragGesture()
.onChanged { value in
offset = value.translation
targetPoint = CGPoint(
x: point2.position.x + offset.width,
y: point2.position.y + offset.height
)
}
.onEnded { value in
point2 = Point(targetPoint)
offset = CGSize()
}
)
}
}
}