SwiftUI中有一个带有均匀点状边框的圆形?

7

我试图创建一个可调整大小的按钮,它周围有一个均匀点状圆形边框。如果你只是放置:

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 这里有一个相关问题,提供了一种解决方案。我试图将其从UIKit适应到SwiftUI结构中,但是失败了。
请问有谁能帮助我找到一种方法来调整“dash”值以创建依赖于半径的均匀虚线边框,或者创建一个自定义形状?

这个问题有回答吗?如何使用SwiftUI绘制弧形? - lorem ipsum
谢谢您的建议,我刚刚尝试了一下,但不幸的是.strokedPath函数有与我想避免的相同问题 :/ - danylo.net
2个回答

11

我有一个使用纯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)
    }
}

1
哇塞!非常感谢,您的解决方案非常简单明了。我花了一点时间才理解周长/点数创建了每个点周围的距离,并减去点本身的大小创造了剩余空间。看到如此完美的比例是如此令人满意。 - danylo.net
2
这是一个有趣的小练习。本质上,我知道问题所在,但我无法直接陈述。有一段时间,我认为我需要比简单的周长更多的东西来解决它。当时已经很晚了,而且我还没有吃晚饭。我吃过晚饭后,完成起来就容易多了。 - Yrb
惊人的解决方案! - Chris

2

使用带虚线的圆形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)
          }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接