SwiftUI Canvas中利用DragGesture实现直线绘制的问题及需求
解决SwiftUI Canvas绘制直线的轨迹混乱问题
问题说明
尝试使用SwiftUI的Canvas和DragGesture绘制直线,但当前代码只能得到无固定轨迹的混乱线条,需要实现拖拽时实时显示从起点到当前位置的直线,拖拽结束后固定该直线的效果。
当前效果

期望效果

当前代码问题分析
原代码在DragGesture的onChanged中不断将当前位置追加到lines数组,然后遍历数组绘制所有点的连线,导致轨迹是连续拖拽路径的折线,而非从固定起点到当前位置的直线,同时缺少拖拽开始/结束的状态管理,无法固定已绘制的直线。
修改后的代码
import SwiftUI struct GraphicDictView: View { // 存储已完成的直线(每条直线包含起点和终点) @State private var completedLines: [(start: CGPoint, end: CGPoint)] = [] // 存储正在绘制的临时直线(起点+当前拖拽位置) @State private var currentLine: (start: CGPoint, end: CGPoint)? // 跟随拖拽的圆点位置 @State private var circlePosition = CGPoint() var body: some View { Canvas { context, _ in // 绘制已完成的所有直线 for line in completedLines { let path = Path { p in p.move(to: line.start) p.addLine(to: line.end) } context.stroke(path, with: .color(.blue), lineWidth: 2) } // 绘制正在拖拽的临时直线 if let currentLine = currentLine { let path = Path { p in p.move(to: currentLine.start) p.addLine(to: currentLine.end) } context.stroke(path, with: .color(.blue), lineWidth: 2) } // 绘制跟随的蓝色圆点 context.fill( Path(ellipseIn: CGRect( x: circlePosition.x - 7, y: circlePosition.y - 7, width: 14, height: 14 )), with: .color(.blue) ) } .gesture( DragGesture() .onStarted { value in // 拖拽开始时记录起点,初始化临时直线 currentLine = (start: value.location, end: value.location) circlePosition = value.location } .onChanged { value in // 拖拽过程中更新临时直线的终点和圆点位置 currentLine?.end = value.location circlePosition = value.location } .onEnded { value in // 拖拽结束时,将临时直线加入已完成数组,清空临时直线 if let line = currentLine { completedLines.append(line) } currentLine = nil } ) } }
关键改动说明
- 状态拆分:用
completedLines存储已固定的直线,currentLine存储正在绘制的临时直线,避免轨迹混乱 - 手势全生命周期处理:
onStarted:记录拖拽起点,初始化临时直线onChanged:实时更新临时直线的终点,同步圆点位置onEnded:将临时直线保存到已完成数组,清空临时状态
- Canvas绘制逻辑:先绘制已完成的直线,再绘制临时直线,确保层级正确
内容的提问来源于stack exchange,提问作者Alex Bro
相关产品推荐
相关产品推荐

