SwiftUI 半环形进度条overlay圆形指示器x/y坐标计算问题
半环形进度条滑块定位实现方案
核心坐标计算公式
无需深究数学原理,直接套用以下固定逻辑即可实现滑块的正确定位:
- 基础参数定义
- 半环轨道半径:
r = geometry.size.width / 2 - 进度完成率:
progress = CGFloat(configuration.fractionCompleted ?? 0),取值范围为0~1 - 进度对应弧度:
radian = .pi * (1 - progress)(半环总角度为180度,对应π弧度)
- 半环轨道半径:
- 坐标计算
- 半环中心X坐标:
centerX = geometry.size.width / 2 - 半环中心Y坐标:
centerY = r(适配SwiftUI Y轴向下为正的坐标规则) - 滑块最终X坐标:
x = centerX + r * cos(radian) - 滑块最终Y坐标:
y = centerY - r * sin(radian)
- 半环中心X坐标:
完整可运行代码
GeometryReader { geometry in ZStack(alignment: .topLeading) { // 半环背景轨道 Circle() .trim(from: 0.0, to: 0.5) .stroke(Color.blue, style: StrokeStyle(lineWidth: 5)) .rotationEffect(.degrees(-180)) .frame(width: geometry.size.width) .opacity(0.5) // 已完成进度条 Circle() .trim(from: 0.0, to: CGFloat(configuration.fractionCompleted ?? 0) / 2) .stroke(Color.blue, style: StrokeStyle(lineWidth: 5)) .rotationEffect(.degrees(-180)) .frame(width: geometry.size.width) // 进度滑块 Circle() .fill(Color.blue) .frame(width: 20, height: 20) .position( x: { let r = geometry.size.width / 2 let progress = CGFloat(configuration.fractionCompleted ?? 0) let radian = .pi * (1 - progress) return geometry.size.width / 2 + r * cos(radian) }(), y: { let r = geometry.size.width / 2 let progress = CGFloat(configuration.fractionCompleted ?? 0) let radian = .pi * (1 - progress) return r - r * sin(radian) }() ) } // 固定容器高度为宽度的一半,适配半环尺寸 .frame(height: geometry.size.width / 2) }
效果参考

内容的提问来源于stack exchange,提问作者cole
相关产品推荐
相关产品推荐

