当布尔值为真时触发动画

Posted

技术标签:

【中文标题】当布尔值为真时触发动画【英文标题】:Triggering an animation when a boolean is true 【发布时间】:2021-02-19 19:33:21 【问题描述】:

我想制作一个像这样的动画:一个带有视图的 ZStack,上面是一个紫色矩形,最初的比例为 0,不透明度为 0,位于屏幕的中心。

当动画被触发时,会发生两个动画:

    矩形的比例在 0.4 秒内从 0 增加到 1。 矩形的不透明度在 0.3 秒内从 0 增加到 1,在 0.1 秒内从 1 增加到 0。

这是我试图这样做:

struct ContentView : View 

  @State private var scale: CGFloat = 0
  @State private var scaleSeed: CGFloat = 0.1
  @State private var counter: Int = 1
  @State private var triggerFlashAnimation = false 
    didSet 
      scale = 0
      counter = 1
    
  


  var body: some View 
    
    ZStack 
      Text("Hello")

      if triggerFlashAnimation 
        Rectangle()
          .background(Color.purple)
          .scaleEffect(scale)
          .onAppear 
            scale += scaleSeed
            counter += 1
          
      

我认为这会为比例设置动画,但这非常粗糙,因为我无法控制时间。

我记得在 CoreGraphics 时代,您可以为时间和值定义关键帧。

如何使用 SwiftUI 做到这一点。我的意思是为每个参数定义关键帧和值的精确动画?

我四处搜索,一无所获。

【问题讨论】:

我认为 SwiftUI 不支持关键帧动画。 【参考方案1】:

SwiftUI 不支持我们在 CoreAnimation 中习惯使用的关键帧(来源:https://***.com/a/56908148/560942、https://swiftui-lab.com/swiftui-animations-part1/)。

但是,您可以使用delay 对链接进行变体:

struct ContentView : View 
    
    @State private var scale: CGFloat = 0
    @State private var opacity: Double = 0
    @State private var triggerFlashAnimation = false
    
    func triggerAnimationActions() 
        withAnimation(.linear(duration: 0.4)) 
            scale = 1
        
        withAnimation(.linear(duration: 0.3)) 
            opacity = 1
        
        withAnimation(Animation.linear(duration: 0.1).delay(0.3)) 
            opacity = 0
        
        
        // reset
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) 
            triggerFlashAnimation = false
            scale = 0
            opacity = 0
        
    
    
    var body: some View 
        ZStack 
            Text("Hello")
            
            Button(action:  triggerFlashAnimation = true ) 
                Text("Button")
            .onChange(of: triggerFlashAnimation)  (val) in
                if val 
                    triggerAnimationActions()
                
            
            
            if triggerFlashAnimation 
                Rectangle()
                    .fill(Color.purple.opacity(opacity))
                    .frame(width: 100, height: 100)
                    .scaleEffect(scale)
            
            
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    


可能还值得研究 AnimatableModifier ,它允许您定义一个 animatableData 属性,您可以在其中插入值、基于动画的特定状态的精确帧等,但据我所知,不考虑完全用于计时——它只是让您根据当前动画的精确值设置状态。阅读有关AnimatableModifier 的好资源:https://www.hackingwithswift.com/quick-start/swiftui/how-to-animate-the-size-of-text

【讨论】:

以上是关于当布尔值为真时触发动画的主要内容,如果未能解决你的问题,请参考以下文章

当属性和数据值为真时 WPF 触发

Swift 3 - 当布尔为真时如何移动精灵节点?

ASP .Net MVC 应用程序:当 db-entity(“课程”)的布尔属性(“已观看”)为真时如何向用户显示

断言与异常

基本布尔逻辑——如何仅在另一个条件为真时测试条件

使用数据注释强制模型的布尔值为真