SwiftUI 动画:如何延迟重复动画

Posted

技术标签:

【中文标题】SwiftUI 动画:如何延迟重复动画【英文标题】:SwiftUI animation: How to stagger repeating animation with delay 【发布时间】:2020-03-25 15:46:52 【问题描述】:

尝试在 SwiftUI 中实现以下动画,发现完全不可能:

总结效果:一个重复的脉冲,以交错的延迟为每个片段设置动画。对于每个段:

从不透明度 = 0.5 开始,比例 = 1 动画到不透明度 = 1.0,比例 = 1.3 动画曲线以较长的缓出速度快速开始

另外,每个‘脉冲’之间都有延迟。

我使用 SwiftUI 最接近这一点的是使用 .repeatForever 修饰符的连续重复动画。 (下面的代码。暂时忽略时间不匹配。)

如何在动画的每个循环之间添加延迟?

下面是我的代码的结果:

import SwiftUI

struct ArrowShape : Shape 

    func path(in rect: CGRect) -> Path 
        var path = Path()

        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: rect.size.width, y: rect.size.height/2.0))
        path.addLine(to: CGPoint(x: 0, y: rect.size.height))

        return path
    


struct Arrows: View 
    private let arrowCount = 3

    @State var scale:CGFloat = 1.0
    @State var fade:Double = 0.5

    var body: some View 

        ZStack 
            Color(red: 29.0/255.0, green: 161.0/255.0, blue: 224.0/255.0).edgesIgnoringSafeArea(.all)

            HStack
                ForEach(0..<self.arrowCount)  i in
                    ArrowShape()
                        .stroke(style: StrokeStyle(lineWidth: CGFloat(10),
                                                  lineCap: .round,
                                                  lineJoin: .round ))
                        .foregroundColor(Color.white)
                        .aspectRatio(CGSize(width: 28, height: 70), contentMode: .fit)
                        .frame(maxWidth: 20)
                        .animation(nil)
                        .opacity(self.fade)
                        .scaleEffect(self.scale)
                        .animation(
                            Animation.easeOut(duration: 0.8)
                            .repeatForever(autoreverses: true)
                            .delay(0.2 * Double(i))
                        )
                
            

            .onAppear() 
                self.scale = 1.2
                self.fade = 1.0
            
        
    




struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        Arrows()
    

【问题讨论】:

***.com/a/29158824/793607 展示了如何在每个动画之后制作带有延迟的动画循环。 @HalR 嗯?这个答案就是 UIKit 解决方案。 我将其归咎于太多天的孤立。 :) 【参考方案1】:

我认为您可以使用 Timer 和 DispatchQueue 来实现它,试试这个,看看它是否按您的意愿工作

struct Arrows: View 
    private let arrowCount = 3

    let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()

    @State var scale:CGFloat = 1.0
    @State var fade:Double = 0.5

    var body: some View 

        ZStack 
            Color(red: 29.0/255.0, green: 161.0/255.0, blue: 224.0/255.0).edgesIgnoringSafeArea(.all)

            HStack
                ForEach(0..<self.arrowCount)  i in
                    ArrowShape()
                        .stroke(style: StrokeStyle(lineWidth: CGFloat(10),
                                                  lineCap: .round,
                                                  lineJoin: .round ))
                        .foregroundColor(Color.white)
                        .aspectRatio(CGSize(width: 28, height: 70), contentMode: .fit)
                        .frame(maxWidth: 20)
                        .animation(nil)
                        .opacity(self.fade)
                        .scaleEffect(self.scale)
                        .animation(
                            Animation.easeOut(duration: 0.5)
                            //.repeatForever(autoreverses: true)
                            .repeatCount(1, autoreverses: true)
                            .delay(0.2 * Double(i))
                        )
                .onReceive(self.timer)  _ in
                     self.scale = self.scale > 1 ?  1 : 1.2
                     self.fade = self.fade > 0.5 ? 0.5 : 1.0
                     DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) 
                                self.scale = 1
                                self.fade = 0.5
                            
                    
            
        
    

【讨论】:

产生想要的效果。谢谢! CAVEAT:仅当视图从未刷新时才有效。如果重建包含此视图的视图层次结构,则计时器没有机会触发。

以上是关于SwiftUI 动画:如何延迟重复动画的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:如何使用延迟在两个图像之间设置动画过渡?

SwiftUI 反向动画延迟移除

SwiftUI动画:如何移动然后显示?

SwiftUI ForEach 没有动画延迟

Swiftui NavigationView 计时器延迟

在 SwiftUI 图像上重复动画