I'm trying to create a resizable button that has an evenly dotted circle border around it. If you simply put:
Circle()
.stroke(color, style: StrokeStyle(lineWidth: 3, lineCap: .butt, dash: [3, radius / 3.82]))
.frame(width: radius * 2, height: radius * 2)
There might be an uneven distribution of dots as you can see in the below image:
Here's a related question with a solution which I tried adapting from UIKit into a SwiftUI struct but also failed.
Can someone please help me either find a way to adapt that "dash" value to create an evenly dashed stroked border with dependence on the radius OR create a custom shape instead?
I have an answer in pure SwiftUI. I think the issue you are running into is simply that you are drawing for part and skipping for part, and you have to take both into account.
Therefore, you need to come up with the circumference, divide it into the segments of 1 drawn part + 1 undrawn part. The drawn part is simply what looks good to you, so the undrawn part is the segment less the drawn part. You then plug both of those values into the StrokeStyle.dash and you get evenly spaced dots.
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)
}
}