【问题标题】:Animating Paths in SwiftUI ShapesSwiftUI Shapes 中的动画路径
【发布时间】:2019-12-15 05:07:57
【问题描述】:

我真的很喜欢 SF Symbol 集合中的 Timer 符号,我想在 SwiftUI 中为它制作动画。有几种不同的方法可以做到这一点,最简单的一种是制作面部图像和手部图像,将它们拍在 ZStack 中,然后为 Image("hand") 视图设置动画。 我还可以将脸部和手部绘制为单独的形状,然后以相同的方式堆叠和制作动画,如下所示:

struct TimerFace: Shape {
    func path(in rect: CGRect) -> Path {
        var facePath = Path()
        facePath.move(to: CGPoint(x: 50, y: 100))
        facePath.addCurve(to: CGPoint(x: 100, y: 50), control1: CGPoint(x: 77.61, y: 100), control2: CGPoint(x: 100, y: 77.61))
        facePath.addCurve(to: CGPoint(x: 50.05, y: 0), control1: CGPoint(x: 100, y: 22.44), control2: CGPoint(x: 77.66, y: 0))
        facePath.addCurve(to: CGPoint(x: 44.74, y: 5.12), control1: CGPoint(x: 46.75, y: 0), control2: CGPoint(x: 44.74, y: 1.96))
        facePath.addLine(to: CGPoint(x: 44.74, y: 22.01))
        facePath.addCurve(to: CGPoint(x: 49.38, y: 26.79), control1: CGPoint(x: 44.74, y: 24.74), control2: CGPoint(x: 46.65, y: 26.79))
        facePath.addCurve(to: CGPoint(x: 54.02, y: 22.01), control1: CGPoint(x: 52.11, y: 26.79), control2: CGPoint(x: 54.02, y: 24.74))
        facePath.addLine(to: CGPoint(x: 54.02, y: 11.24))
        facePath.addCurve(to: CGPoint(x: 88.76, y: 50), control1: CGPoint(x: 73.68, y: 13.3), control2: CGPoint(x: 88.76, y: 29.81))
        facePath.addCurve(to: CGPoint(x: 50, y: 88.8), control1: CGPoint(x: 88.76, y: 71.44), control2: CGPoint(x: 71.58, y: 88.8))
        facePath.addCurve(to: CGPoint(x: 11.24, y: 50), control1: CGPoint(x: 28.47, y: 88.8), control2: CGPoint(x: 11.2, y: 71.44))
        facePath.addCurve(to: CGPoint(x: 19.62, y: 26.08), control1: CGPoint(x: 11.29, y: 41.05), control2: CGPoint(x: 14.4, y: 32.63))
        facePath.addCurve(to: CGPoint(x: 19.67, y: 17.8), control1: CGPoint(x: 21.67, y: 23.06), control2: CGPoint(x: 22.11, y: 20.19))
        facePath.addCurve(to: CGPoint(x: 11, y: 19.04), control1: CGPoint(x: 17.32, y: 15.5), control2: CGPoint(x: 13.44, y: 15.74))
        facePath.addCurve(to: CGPoint(x: 0, y: 50), control1: CGPoint(x: 4.16, y: 27.56), control2: CGPoint(x: 0, y: 38.37))
        facePath.addCurve(to: CGPoint(x: 50, y: 100), control1: CGPoint(x: 0, y: 77.61), control2: CGPoint(x: 22.39, y: 100))
        return facePath
    }
}

struct TimerHand: Shape {
    func path(in rect: CGRect) -> Path {
        var handPath = Path()
        handPath.move(to: CGPoint(x: 7.93, y: 40))
        handPath.addCurve(to: CGPoint(x: 15.8, y: 29.75), control1: CGPoint(x: 13.5, y: 39.9), control2: CGPoint(x: 16.88, y: 35.25))
        handPath.addLine(to: CGPoint(x: 10.76, y: 2.77))
        handPath.addCurve(to: CGPoint(x: 5.22, y: 2.77), control1: CGPoint(x: 10.03, y: -0.92), control2: CGPoint(x: 5.95, y: -0.92))
        handPath.addLine(to: CGPoint(x: 0.21, y: 29.72))
        handPath.addCurve(to: CGPoint(x: 7.93, y: 40), control1: CGPoint(x: -0.9, y: 35.25), control2: CGPoint(x: 2.44, y: 39.93))
        return handPath
    }
}

struct TimerView: View {
    @State private var rotation = 0.0

    var body: some View {
        VStack {
            ZStack {
                TimerFace().frame(CGSize(width: 100,height: 100), alignment: .center)
                TimerHand().frame(CGSize(width: 16,height: 64), alignment: .center)
                    .rotationEffect(.degrees(rotation), anchor: .center)
            }
            Slider(value: $rotation, in: 0...360, step: 1.0)
        }
    }
}

应该是这样的

我确实认为这有点像“作弊”。关于如何以“正确”方式执行此操作的任何建议,而不是动画手框架,动画路径本身?

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    您可以将旋转放在框架内:

            struct TimerHand: Shape {
    
                var degree : Double
    
                func path(in rect: CGRect) -> Path {
                    var handPath = Path()
                    handPath.move(to: CGPoint(x: 7.93, y: 40))
                    handPath.addCurve(to: CGPoint(x: 15.8, y: 29.75), control1: CGPoint(x: 13.5, y: 39.9), control2: CGPoint(x: 16.88, y: 35.25))
                    handPath.addLine(to: CGPoint(x: 10.76, y: 2.77))
                    handPath.addCurve(to: CGPoint(x: 5.22, y: 2.77), control1: CGPoint(x: 10.03, y: -0.92), control2: CGPoint(x: 5.95, y: -0.92))
                    handPath.addLine(to: CGPoint(x: 0.21, y: 29.72))
                    handPath.addCurve(to: CGPoint(x: 7.93, y: 40), control1: CGPoint(x: -0.9, y: 35.25), control2: CGPoint(x: 2.44, y: 39.93))
                    return handPath.rotation(.degrees(degree), anchor: .center).path(in: rect)
                }
            }
    
            struct TimerView: View {
                @State private var rotation = 0.0
    
                var body: some View {
                    VStack {
                        ZStack {
                            TimerFace().frame(width: 100,height: 100, alignment: .center)
                            TimerHand(degree: rotation).frame(width: 16,height: 64, alignment: .center)
                        }
                        Slider(value: $rotation, in: 0...360, step: 1.0)
                    }
                }
            }
    

    【讨论】:

    • 那真是太好了。
    猜你喜欢
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 2020-04-20
    • 2016-02-14
    相关资源
    最近更新 更多