SwiftUI轨迹绘制异常求助:拖拽圆形轨迹呈矩形而非平滑曲线
问题分析与修复方案
你的轨迹呈现矩形而非平滑曲线,核心是三个关键逻辑错误:
1. Path绘制逻辑断裂
循环里每次调用addLine(to:)后又执行move(to:),会让每个点都成为新路径的起点,所有线段都孤立存在,根本无法连成连续曲线。应该只在循环前设置初始起点,循环内仅调用addLine(to:)来连接点。
2. 轨迹纵向坐标计算不稳定
你用(geo.size.height / 2) / CGFloat(track.count)计算Y坐标,当track.count达到100并开始移除元素时,数组长度会在99和100之间波动,导致高度值跳变,轨迹出现上下抖动。需要固定轨迹区域的总高度,按固定步长分配每个点的Y坐标。
3. Timer触发过于频繁
Timer.publish(every: 0.001)相当于每秒触发1000次,不仅浪费性能,还会让轨迹点过于密集,反而影响流畅度。建议调整为0.02~0.05秒的间隔,平衡流畅度和性能。
修复后的完整代码
import SwiftUI struct ContentView: View { @State private var track = [CGFloat]() @State private var offset: CGFloat = 0 // 调整Timer间隔为0.02秒(每秒50次) let timer = Timer.publish(every: 0.02, on: .current, in: .common).autoconnect() // 固定轨迹点数量,避免长度波动 private let maxTrackPoints = 100 var body: some View { GeometryReader { geo in ZStack { Color.black Path { path in guard !track.isEmpty else { return } // 固定轨迹区域的总高度为屏幕下半部分 let totalTrackHeight = geo.size.height / 2 // 每个点的纵向步长固定 let yStep = totalTrackHeight / CGFloat(maxTrackPoints - 1) // 设置路径起点 let startX = geo.size.width * track[0] path.move(to: CGPoint(x: startX, y: 0)) // 循环连接所有轨迹点 for i in 1..<track.count { let x = geo.size.width * track[i] let y = yStep * CGFloat(i) path.addLine(to: CGPoint(x: x, y: y)) } } .stroke(lineWidth: 1) .foregroundStyle(.yellow) // 让轨迹显示在屏幕下半部分 .position(x: geo.size.width / 2, y: geo.size.height * 3/4) Circle() .frame(width: 25) .foregroundStyle(.red) .position(x: offset, y: geo.size.height / 2) .gesture( DragGesture() .onChanged { value in offset = min(geo.size.width - 15, max(15, value.location.x)) } ) .onAppear { offset = geo.size.width / 2 } .onReceive(timer) { _ in track.append(offset / geo.size.width) if track.count >= maxTrackPoints { track.removeFirst() } } } } } }
额外优化建议
- 如果想要更平滑的曲线,可以把
addLine(to:)换成addQuadCurve(to:control:)或addCurve(to:control1:control2:),用贝塞尔曲线连接点 - 可以给轨迹添加渐隐效果,让最早的轨迹点透明度更低,增强视觉层次感
内容的提问来源于stack exchange,提问作者Karl Ehrlich
相关产品推荐
相关产品推荐

