如何在SwiftUI中实现手指滑动区域的空心带边框效果?
SwiftUI实现滑动轨迹空心边框效果
核心思路
要实现滑动轨迹区域的空心边框,关键是先生成所有滑动点对应圆的并集区域,再将该区域的轮廓转换为可填充的边框路径,而非直接绘制单个圆的边框。
完整实现代码
struct Circular: View { @State private var touchPoints: [CGPoint] = [] @State private var borderPaths: [Path] = [] // 支持多次拖动叠加边框 @State private var isDragging = false // 可自定义配置参数 private let circleDiameter: CGFloat = 30 private let borderWidth: CGFloat = 2 private let dragPointInterval: CGFloat = 10 // 过滤过近的点,优化性能 var body: some View { ZStack { Image("img4") .resizable() .scaledToFit() // 拖动过程中显示临时轨迹(可选,和原效果一致) if isDragging { Color.red .mask(eraserShape()) .blendMode(.colorDodge) } // 所有已完成的拖动边框 ForEach(0..<borderPaths.count, id: \.self) { index in borderPaths[index] .fill(Color.blue) // 边框颜色可自定义 } } .gesture( DragGesture(minimumDistance: 0) .onChanged { value in isDragging = true // 避免添加过于密集的点,减少性能消耗 guard let lastPoint = touchPoints.last else { touchPoints.append(value.location) return } let distance = hypot(value.location.x - lastPoint.x, value.location.y - lastPoint.y) if distance >= dragPointInterval { touchPoints.append(value.location) } } .onEnded { _ in isDragging = false // 生成所有圆的并集路径 var unionPath = Path() for point in touchPoints { let rect = CGRect( x: point.x - circleDiameter / 2, y: point.y - circleDiameter / 2, width: circleDiameter, height: circleDiameter ) unionPath.addEllipse(in: rect) } // 将并集路径转换为边框路径 borderPaths.append(unionPath.strokedPath(StrokeStyle(lineWidth: borderWidth))) touchPoints.removeAll() // 清空当前拖动点,准备下一次操作 } ) } private func eraserShape() -> Path { var path = Path() for point in touchPoints { let rect = CGRect( x: point.x - circleDiameter / 2, y: point.y - circleDiameter / 2, width: circleDiameter, height: circleDiameter ) path.addEllipse(in: rect) } return path } }
关键细节说明
- 并集路径生成:将所有滑动点对应的椭圆添加到同一个
Path中,SwiftUI默认的非零缠绕数填充规则会自动合并重叠区域,得到完整的滑动覆盖范围。 - 边框路径转换:调用
strokedPath(_:)方法,将并集区域路径转换为描边后的路径——这个路径的填充区域正好是原并集区域的边缘边框,填充后自然呈现空心效果。 - 性能优化:通过判断点之间的距离过滤密集点,避免数组过大导致的性能问题。
- 多拖动支持:用数组
borderPaths保存每次拖动生成的边框,实现多次滑动叠加的效果。
内容的提问来源于stack exchange,提问作者dshn
相关产品推荐
相关产品推荐

