SwiftUI 中带有均匀虚线边框的圆圈?

时间:2021-07-01 22:32:18

标签: ios swift swiftui geometry stroke

我正在尝试创建一个可调整大小的按钮,该按钮周围有一个均匀的虚线圆圈边框。如果你简单地说:

Circle()
  .stroke(color, style: StrokeStyle(lineWidth: 3, lineCap: .butt, dash: [3, radius / 3.82]))
  .frame(width: radius * 2, height: radius * 2)

如下图所示,点的分布可能不均匀:enter image description here

这是一个带有解决方案的 related question,我尝试将其从 UIKit 改编为 SwiftUI 结构,但也失败了。

有人可以帮我找到一种方法来调整“破折号”值以创建依赖于半径的均匀虚线描边边框还是创建自定义形状?

2 个答案:

答案 0 :(得分:1)

使用circle with dash lines uiview中的一些代码

我得到了适用于 Swiftui 的测试代码:

    import SwiftUI
    
    @main
    struct TestApp: App {
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    
    struct ContentView: View {

    @State var color = Color.blue
    @State var radius = CGFloat(128)
    @State var painted = CGFloat(6)
    @State var unpainted = CGFloat(6)
    
    let count: CGFloat = 30
    let relativeDashLength: CGFloat = 0.25

    var body: some View {
        Circle()
            .stroke(color, style: StrokeStyle(lineWidth: 3, lineCap: .butt, dash: [painted, unpainted]))
          .frame(width: radius * 2, height: radius * 2)
          .onAppear {
              let dashLength = CGFloat(2 * .pi * radius) / count
              painted = dashLength * relativeDashLength
              unpainted = dashLength * (1 - relativeDashLength)
          }
    }
}

答案 1 :(得分:1)

我有一个纯 SwiftUI 的答案。我认为您遇到的问题只是您正在为部分绘图而跳过部分,您必须将两者都考虑在内。

因此,您需要想出周长,将其分成1个绘制部分+ 1个未绘制部分的部分。绘制的部分只是你看起来不错的部分,所以未绘制的部分是减去绘制部分的线段。然后将这两个值都插入到 StrokeStyle.dash 中,就会得到均匀分布的点。

import SwiftUI

struct ContentView: View {
    let radius: CGFloat = 100
    let pi = Double.pi
    let dotCount = 10
    let dotLength: CGFloat = 3
    let spaceLength: CGFloat

    init() {
        let circumerence: CGFloat = CGFloat(2.0 * pi) * radius
        spaceLength = circumerence / CGFloat(dotCount) - dotLength
    }
    
    var body: some View {
        Circle()
            .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, lineCap: .butt, lineJoin: .miter, miterLimit: 0, dash: [dotLength, spaceLength], dashPhase: 0))
            .frame(width: radius * 2, height: radius * 2)
    }
}
相关问题