SwiftUI - 脉动动画和改变颜色

Posted

技术标签:

【中文标题】SwiftUI - 脉动动画和改变颜色【英文标题】:SwiftUI - Pulsating Animation & Change Colour 【发布时间】:2020-02-09 17:12:01 【问题描述】:

我正在尝试根据某物的状态更改动画的颜色。颜色变化有效,但它会用它为以前的(橙色)颜色设置动画。我不太明白为什么两种颜色都会显示。有什么想法吗?

struct PulsatingView: View 

    var state = 1

    func colourToShow() -> Color 
        switch state 
        case 0:
            return Color.red
        case 1:
            return Color.orange
        case 2:
            return Color.green
        default:
            return Color.orange
        
    

    @State var animate = false
    var body: some View 
        VStack 
            ZStack 
                Circle().fill(colourToShow().opacity(0.25)).frame(width: 40, height: 40).scaleEffect(self.animate ? 1 : 0)
                Circle().fill(colourToShow().opacity(0.35)).frame(width: 30, height: 30).scaleEffect(self.animate ? 1 : 0)
                Circle().fill(colourToShow().opacity(0.45)).frame(width: 15, height: 15).scaleEffect(self.animate ? 1 : 0)
                Circle().fill(colourToShow()).frame(width: 6.25, height: 6.25)
            
            .onAppear  self.animate.toggle() 
            .animation(Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true))
        
    

【问题讨论】:

【参考方案1】:

您更改了颜色,但设置的动画视图永远没有改变 - 它保持原样并按照指定的方式继续 - 永远。所以需要重新设置动画。

请在下面找到完整的模块演示代码(使用 Xcode 11.2 / ios 13.2 测试)。这个想法是使用ObservableObject 视图模型,因为它允许刷新视图并在接收时执行一些操作。因此接收颜色变化可以重置和查看颜色和动画。

import SwiftUI
import Combine

class PulsatingViewModel: ObservableObject 
    @Published var colorIndex = 1


struct PulsatingView: View 

    @ObservedObject var viewModel: PulsatingViewModel

    func colourToShow() -> Color 
        switch viewModel.colorIndex 
        case 0:
            return Color.red
        case 1:
            return Color.orange
        case 2:
            return Color.green
        default:
            return Color.orange
        
    

    @State var animate = false
    var body: some View 
        VStack 
            ZStack 
                Circle().fill(colourToShow().opacity(0.25)).frame(width: 40, height: 40).scaleEffect(self.animate ? 1 : 0)
                Circle().fill(colourToShow().opacity(0.35)).frame(width: 30, height: 30).scaleEffect(self.animate ? 1 : 0)
                Circle().fill(colourToShow().opacity(0.45)).frame(width: 15, height: 15).scaleEffect(self.animate ? 1 : 0)
                Circle().fill(colourToShow()).frame(width: 6.25, height: 6.25)
            
            .onAppear  self.animate = true 
            .animation(animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : .default)
            .onReceive(viewModel.$colorIndex)  _ in
                self.animate = false
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) 
                    self.animate = true
                
            
        
    


struct TestPulseColorView: View 
    private var model = PulsatingViewModel()
    var body: some View 
        VStack 
            Spacer()
            PulsatingView(viewModel: model)
            Spacer()
            Button("Toggle")  self.model.colorIndex = Int.random(in: 0...2) 
        
    


struct TestPulseColorView_Previews: PreviewProvider 
    static var previews: some View 
        TestPulseColorView()
    

【讨论】:

Asperi,每次看到你的回答,我都会学到一些新东西。

以上是关于SwiftUI - 脉动动画和改变颜色的主要内容,如果未能解决你的问题,请参考以下文章

如何摆脱不需要的 SwiftUI 动画?

SwiftUI - 如何脉动图像不透明度?

SwiftUI 如何临时为视图颜色的前景颜色设置动画?

如何修复适用于 SwiftUI 中文本的动画制作帧问题/错误?

使用情节提要和 DataTrigger 制作一个脉动的 TextBlock - 动画中的异常

Google Maps Swift 中的脉动标记动画