Wie erstelle ich eine SwiftUI RoundedStar-Form?
Dies ist eine selbst beantwortete Frage, die bei Stack Overflow durchaus akzeptabel (und sogar empfohlen) ist. Es geht darum, etwas Nützliches für andere zu teilen.
SwiftUI hat eine RoundedRectangle Shape. Es wäre schön, einen fünfzackigen Stern mit abgerundeten Spitzen zu haben, der zum Füllen, Ausschneiden und Animieren verwendet werden könnte.
Diese Antwort zum Stapelüberlauf zeigt, wie Sie RoundedStareine benutzerdefinierte UIViewVerwendung erstellen UIBezierPath.
Wie kann dieser Code angepasst werden SwiftUIals Shapedie animiert werden können?
Antworten
Hier ist der RoundedStarCode, der als animierbare SwiftUI angepasst wurde Shape:
// Five-point star with rounded tips
struct RoundedStar: Shape {
var cornerRadius: CGFloat
var animatableData: CGFloat {
get { return cornerRadius }
set { cornerRadius = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
let center = CGPoint(x: rect.width / 2, y: rect.height / 2)
let r = rect.width / 2
let rc = cornerRadius
let rn = r * 0.95 - rc
// start angle at -18 degrees so that it points up
var cangle = -18.0
for i in 1 ... 5 {
// compute center point of tip arc
let cc = CGPoint(x: center.x + rn * CGFloat(cos(Angle(degrees: cangle).radians)), y: center.y + rn * CGFloat(sin(Angle(degrees: cangle).radians)))
// compute tangent point along tip arc
let p = CGPoint(x: cc.x + rc * CGFloat(cos(Angle(degrees: cangle - 72).radians)), y: cc.y + rc * CGFloat(sin(Angle(degrees: (cangle - 72)).radians)))
if i == 1 {
path.move(to: p)
} else {
path.addLine(to: p)
}
// add 144 degree arc to draw the corner
path.addArc(center: cc, radius: rc, startAngle: Angle(degrees: cangle - 72), endAngle: Angle(degrees: cangle + 72), clockwise: false)
// Move 144 degrees to the next point in the star
cangle += 144
}
return path
}
}
Der Code ist der UIBezierPathVersion sehr ähnlich, außer dass er den neuen AngleTyp verwendet, der einen einfachen Zugriff auf degreesund bietet radians. Der Code zum Zeichnen des gedrehten Sterns wurde entfernt, da es einfach ist, einer SwiftUI-Form mit dem .rotationEffect(angle:)Ansichtsmodifikator eine Drehung hinzuzufügen .
Demonstration:
Hier ist eine Demonstration, die die animierbaren Eigenschaften der cornerRadiusEinstellung zeigt und zeigt, wie die verschiedenen cornerRadiusEinstellungen auf einem Vollbildstern aussehen.
struct ContentView: View {
@State private var radius: CGFloat = 0.0
var body: some View {
ZStack {
Color.blue.edgesIgnoringSafeArea(.all)
VStack(spacing: 40) {
Spacer()
RoundedStar(cornerRadius: radius)
.aspectRatio(1, contentMode: .fit)
.foregroundColor(.yellow)
.overlay(Text(" cornerRadius: \(Int(self.radius)) ").font(.body))
HStack {
ForEach([0, 10, 20, 40, 80, 200], id: \.self) { value in
Button(String(value)) {
withAnimation(.easeInOut(duration: 0.3)) {
self.radius = CGFloat(value)
}
}
.frame(width: 50, height: 50)
.foregroundColor(.black)
.background(Color.yellow.cornerRadius(8))
}
}
Spacer()
}
}
}
}
Laufen in Swift Playgrounds auf dem iPad
Dies läuft wunderbar auf einem iPad in der Swift Playgrounds App. Einfach hinzufügen:
import PlaygroundSupport
oben und
PlaygroundPage.current.setLiveView(ContentView())
Am Ende.
Verwenden der RoundedStar-Form zum Erstellen der EU-Flagge
struct ContentView: View {
let radius: CGFloat = 100
let starWidth: CGFloat = 36
let numStars = 12
var body: some View {
ZStack {
Color.blue
ForEach(0..<numStars) { n in
RoundedStar(cornerRadius: 0)
.frame(width: starWidth, height: starWidth)
.offset(x: radius * cos(CGFloat(n) / CGFloat(numStars) * 2 * .pi), y: radius * sin(CGFloat(n) / CGFloat(numStars) * 2 * .pi))
.foregroundColor(.yellow)
}
}
}
}