👔Polygon

⬆️ 需要: Vector2D, floating +−⨉÷ int
// 2022.03.01
import SwiftUI
import Extensions    // FloatingPoint+
import Protocols     // Vector2D
/// an animatable polygon shape
/// ```
/// Polygon(sides: 6, scale: 1.2)
/// Polygon(5)
/// ```
public struct Polygon: Shape {
    
    var sides: CGFloat
    var scale: CGFloat = 1.0
    
    public init(sides: CGFloat, scale: CGFloat = 1.0) {
        self.sides = sides
        self.scale = scale
    }
    
    // ⭐️ `animatableData` (AnimatablePair)
    public var animatableData: AnimatablePair<CGFloat, CGFloat> {
        get { AnimatablePair(sides, scale) }
        // ⭐️ set new animation value
        set {
            sides = newValue.first
            scale = newValue.second
        }
    }
    
    public func path(in rect: CGRect) -> Path {
        
        let r = scale * rect.minSide / 2   // radius
        let c = rect.center                // polygon center
        let a0 = -0.5 * CGFloat.pi         // start angle
        let a = CGFloat.pi / sides * 2     // difference to next angle
        let n = Int(sides.rounded(.up))    // integral sides
        
        return Path { path in 
            path.move(to: c + .polar(r, a0))
            for i in 1..<n {
                path.addLine(to: c + .polar(r, a0 + a * i))
            }
            path.closeSubpath()
        }
    }
}
// convenience init
extension Polygon {
    /// `Polygon(3)`
    public init(_ n: CGFloat) {
        self.init(sides: n)
    }
}⬆️ 需要: .decimalPlaces(), floating +−⨉÷ int
// 2022.03.01
import SwiftUI
struct ContentView: View {
    @State private var sides: CGFloat = 3
    @State private var scale: CGFloat = 1
    var body: some View {
        VStack {
            polygon
            Slider(value: $sides, in: 1...15)
            buttons
        }
        .padding()
    }
}
extension ContentView {
    
    /// polygon
    var polygon: some View {
        Polygon(sides: sides, scale: scale)        // 👔 Polygon
            .stroke(.green)
            .overlay {
                Text("\(scale.decimalPlaces(2))")  // 🌀FloatingPoint+
                    .font(.caption)
                    .bold()
                    .shadow(radius: 6)
            }
            .background {
                Circle().stroke(.secondary)
                Polygon(sides).stroke(.blue)        // 👔 Polygon
            }
            .border(.secondary)
            .frame(height: 200)
    }
    
    /// buttons
    var buttons: some View {
        HStackForEach(1..<10){i in
            Button { 
                withAnimation(.easeInOut(duration: 1.5)) { 
                    sides = 1.0 * i             // 🌀FloatingPoint+
                    scale = CGFloat.random(in: 0.2...1.2)
                }
            } label: { 
                Text("\(i)")
                    .font(.title3).bold()
                    .foregroundColor(.primary)
                    .padding()
                    .background(.pink)
                    .cornerRadius(6)
            }
        }
    }
}- SwiftUI ⟩ Animations ⟩ - Animatable (protocol) - animatableData - conforms to VectorArithmetic (protocol). 
 
- AnimatablePair (struct) 
 
- SwiftUI Lab ⟩ Advanced SwiftUI Animations ⟩ 
- is an Animatable Shape. 
Last updated
Was this helpful?