如何在SwiftUI中对路径进行动画处理 [英] How to Animate Path in SwiftUI

查看:475
本文介绍了如何在SwiftUI中对路径进行动画处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不熟悉SwiftUI,也没有关于这个新框架的文档。我想知道是否有人熟悉如何在SwiftUI中对 Path 进行动画处理。



例如给定一个视图,可以说这个简单的 RingView

  struct RingView:视图{
var body:some View {
GeometryReader {
组中的几何{
//创建外环路径
路径{path在
path.addArc(center:center,
radius:externalRadius,
startAngle:Angle(degrees:0),
endAngle:Angle(degrees:360),
顺时针:true)
}
.stroke(Color.blue)

//创建内圈
Path {
path中的path path.addArc(中心:中心,
radius:externalRadius,
startAngle:Angle(degrees:0),
endAngle:Angle(degrees:180),
顺时针:true)
}
.stroke( Color.red)
.animation(.basic(持续时间:2,曲线:.linear))
}
}
.aspectRatio(1,contentMode:.fit)
}
}

显示的内容是:





现在,我想知道如何对内环进行动画处理,即红线位于蓝线内。我想做的动画将是一个简单的动画,其中的路径从头开始出现并遍历到结束。



使用CoreGraphics和旧版本,这相当简单UIKit框架,但似乎没有在内部路径中添加简单的 .animation(.basic(duration:2,curve:.linear))并显示带有 withAnimation 块可以执行任何操作。



我看过SwiftUI上提供的Apple教程,但实际上它们只涵盖了更深入视图(例如 Image)上的移动/缩放动画。



有关如何为 Path Shape 在SwiftUI中?

解决方案

路径的动画显示在WWDC会话237中(



这是代码:



重要提示:该代码在Xcode Live Previews上没有动画。它需要在模拟器或真实设备上运行。

  import SwiftUI 

struct ContentView:View {
var body:some View {
RingSpinner()。padding(20)
}
}

struct RingSpinner:视图{
@State var pct:Double = 0.0

var animation:Animation {
Animation.basic(持续时间:1.5) .repeatForever(autoreverses:false)
}

变量主体:一些视图{

GeometryReader {
中的几何ZStack {
路径{
中的路径
path.addArc(center:CGPoint(x:geometry.size.width / 2,y:geometry.size.width / 2),
radius:geometry.size.width / 2,
startAngle:角度(度:0),
endAngle:角度(度:360),
Clockwis e:true)
}
.stroke(Color.green,lineWidth:40)

InnerRing(pct:self.pct).stroke(Color.yellow,lineWidth:20 )
}
}
.aspectRatio(1,contentMode:.fit)
.padding(20)
.onAppear(){
withAnimation(self .animation){
self.pct = 1.0
}
}
}

}

struct InnerRing:Shape {
var lagAmmount = 0.35
var pct:Double

func path(在rect中:CGRect)->路径{

let end = pct * 360
var start:如果pct>加倍

(1-lagAmmount){
start = 360 *(2 * pct-1.0)
}否则,如果pct> lagAmmount {
start = 360 *(pct-lagAmmount)
} else {
start = 0
}

var p = Path()

p.addArc(center:CGPoint(x:rect.size.width / 2,y:rect.size.width / 2),
半径:rect.size.width / 2,
startAngle:角度(度:开始),
endAngle:角度(度:结束),
顺时针:false)

return p
}

var animatableData:Double {
get {return pct}
set {pct = newValue}
}
}


Being unfamiliar with SwiftUI and the fact that there is not much documentation on this new framework yet. I was wondering if anyone was familiar with how it would be possible to animate a Path in SwiftUI.

For example given a view, lets say this simple RingView:

struct RingView : View {   
    var body: some View {
        GeometryReader { geometry in
            Group {
                // create outer ring path
                Path { path in
                    path.addArc(center: center,
                                radius: outerRadius,
                                startAngle: Angle(degrees: 0),
                                endAngle: Angle(degrees: 360),
                                clockwise: true)
                }
                .stroke(Color.blue)

                // create inner ring
                Path { path in
                    path.addArc(center: center,
                                radius: outerRadius,
                                startAngle: Angle(degrees: 0),
                                endAngle: Angle(degrees: 180),
                                clockwise: true)
                }
                .stroke(Color.red)
                .animation(.basic(duration: 2, curve: .linear))
            }
        }
        .aspectRatio(1, contentMode: .fit)
    }
}

What is displayed is:

Now I was wondering how we could go about animating the inner ring, that is the red line inside the blue line. The animation I'm looking to do would be a simple animation where the path appears from the start and traverses to the end.

This is rather simple using CoreGraphics and the old UIKit framework but it doesn't seem like adding a simple .animation(.basic(duration: 2, curve: .linear)) to the inner path and displaying the view with a withAnimation block does anything.

I've looked at the provided Apple tutorials on SwiftUI but they really only cover move/scale animations on more in-depth views such as Image.

Any guidance on how to animate a Path or Shape in SwiftUI?

解决方案

Animation of paths is showcased in the WWDC session 237 (Building Custom Views with SwiftUI). The key is using AnimatableData. You can jump ahead to 31:23, but I recommend you start at least at minute 27:47.

You will also need to download the sample code, because conveniently, the interesting bits are not shown (nor explained) in the presentation: https://developer.apple.com/documentation/swiftui/drawing_and_animation/building_custom_views_in_swiftui


More documentation: Since I originally posted the answer, I continued to investigate how to animate Paths and posted an article with an extensive explanation of the Animatable protocol and how to use it with Paths: https://swiftui-lab.com/swiftui-animations-part1/


Update:

I have been working with shape path animations. Here's a GIF.

And here's the code:

IMPORTANT: The code does not animate on Xcode Live Previews. It needs to run either on the simulator or on a real device.

import SwiftUI

struct ContentView : View {
    var body: some View {
        RingSpinner().padding(20)
    }
}

struct RingSpinner : View {
    @State var pct: Double = 0.0

    var animation: Animation {
        Animation.basic(duration: 1.5).repeatForever(autoreverses: false)
    }

    var body: some View {

        GeometryReader { geometry in
            ZStack {
                Path { path in

                    path.addArc(center: CGPoint(x: geometry.size.width/2, y: geometry.size.width/2),
                                radius: geometry.size.width/2,
                                startAngle: Angle(degrees: 0),
                                endAngle: Angle(degrees: 360),
                                clockwise: true)
                }
                .stroke(Color.green, lineWidth: 40)

                InnerRing(pct: self.pct).stroke(Color.yellow, lineWidth: 20)
            }
        }
        .aspectRatio(1, contentMode: .fit)
            .padding(20)
            .onAppear() {
                withAnimation(self.animation) {
                    self.pct = 1.0
                }
        }
    }

}

struct InnerRing : Shape {
    var lagAmmount = 0.35
    var pct: Double

    func path(in rect: CGRect) -> Path {

        let end = pct * 360
        var start: Double

        if pct > (1 - lagAmmount) {
            start = 360 * (2 * pct - 1.0)
        } else if pct > lagAmmount {
            start = 360 * (pct - lagAmmount)
        } else {
            start = 0
        }

        var p = Path()

        p.addArc(center: CGPoint(x: rect.size.width/2, y: rect.size.width/2),
                 radius: rect.size.width/2,
                 startAngle: Angle(degrees: start),
                 endAngle: Angle(degrees: end),
                 clockwise: false)

        return p
    }

    var animatableData: Double {
        get { return pct }
        set { pct = newValue }
    }
}

这篇关于如何在SwiftUI中对路径进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆