SwiftUI实现渐变大小同心点状圆环及屏幕适配问题
实现带渐变圆点的同心圆环SwiftUI视图
现有代码及问题
当前用于绘制同心圆环的SwiftUI视图代码如下:
struct TestView: View { var body: some View { ZStack { Color.red ForEach((0...50), id: \.self) { index in Path { path in var radius = CGFloat(120 + (index * 30)) let center = (x: UIScreen.main.bounds.size.width/2, y: UIScreen.main.bounds.size.height/2) path.move(to: CGPoint(x: center.x + radius, y: center.y)) path.addArc(center: CGPoint(x: center.x, y: center.y), radius: radius, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 360), clockwise: false) } .stroke(Color.white, style: StrokeStyle(lineWidth: 1, lineCap: .round, lineJoin: .round, dash: [3.0])) } } } }
现有问题:
- 虚线样式不符合需求,需替换为圆形圆点
- 圆点大小和间距固定,无法随圆环向外扩展递增
- 使用
UIScreen.main.bounds导致适配安全区域时上下圆弧显示不均,且无法让圆环自然超出屏幕边界
需求目标
- 将虚线替换为圆形圆点,圆点大小与间距随圆环半径增大而逐渐变大
- 圆环超出屏幕边界但保持居中显示,适配安全区域
修改后的实现代码
struct TestView: View { // 可配置参数,方便调整视觉效果 private let ringCount = 50 private let initialRadius: CGFloat = 20 private let radiusStep: CGFloat = 25 private let initialDotSize: CGFloat = 2 private let dotSizeStep: CGFloat = 0.3 private let initialDotSpacing: CGFloat = 8 private let dotSpacingStep: CGFloat = 0.8 var body: some View { ZStack { Color.red .ignoresSafeArea() // 让背景及圆环延伸至安全区域外 // 通过GeometryReader获取容器尺寸,替代UIScreen.main.bounds实现精准居中 GeometryReader { proxy in let center = CGPoint(x: proxy.size.width / 2, y: proxy.size.height / 2) ForEach(0..<ringCount, id: \.self) { index in let radius = initialRadius + CGFloat(index) * radiusStep let dotSize = initialDotSize + CGFloat(index) * dotSizeStep // 利用round线帽特性,将0长度虚线段渲染为圆点,间距随索引递增 let dashSpacing = initialDotSpacing + CGFloat(index) * dotSpacingStep Path { path in path.move(to: CGPoint(x: center.x + radius, y: center.y)) path.addArc(center: center, radius: radius, startAngle: .zero, endAngle: .degrees(360), clockwise: false) } .stroke(Color.white, style: StrokeStyle( lineWidth: dotSize, lineCap: .round, lineJoin: .round, dash: [0, dashSpacing] )) } } } } }
关键修改说明
- 适配安全区域与屏幕边界:
- 使用
GeometryReader获取当前容器的实际尺寸,替代UIScreen.main.bounds,确保在任何布局环境下都能计算出精准的中心位置 - 背景色添加
.ignoresSafeArea(),允许圆环自然延伸到安全区域外,同时保持整体居中对齐
- 使用
- 动态圆点效果:
- 通过
index动态计算每个圆环的lineWidth(即圆点大小)和dash数组的间距值,实现向外扩展时圆点逐渐变大、间距逐渐变宽的效果 - 利用
lineCap: .round特性,将长度为0的虚线段渲染为圆形圆点,避免手动绘制单个圆点带来的性能损耗
- 通过
- 参数可配置:将初始半径、步长、圆点初始大小等参数抽为私有常量,方便快速调整整体视觉风格
内容的提问来源于stack exchange,提问作者batman
相关产品推荐
相关产品推荐

