Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI - Pulsating Animation & Change Colour

I'm trying to change the colour of my animation based on the state of something. The colour change works but it animates the previous (orange) colour with it. I can't quite work out why both colours are showing. Any ideas?

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))
        }
    }
}
like image 953
K. Janjuha Avatar asked Feb 09 '20 17:02

K. Janjuha


People also ask

What is withAnimation SwiftUI?

withAnimation() takes a parameter specifying the kind of animation you want, so you could create a three-second linear animation like this: withAnimation(.linear(duration: 3)) Explicit animations are often helpful because they cause every affected view to animate, not just those that have implicit animations attached.

Does SwiftUI use Core Animation?

SwiftUI uses Core Animation for rendering by default, and its performance is great for most animations. But if you find yourself creating a very complex animation that seems to suffer from lower framerates, you may want to utilize the power of Metal, which is Apple's framework used for working directly with the GPU.

How do I use animation in SwiftUI?

SwiftUI has built-in support for animations with its animation() modifier. To use this modifier, place it after any other modifiers for your views, tell it what kind of animation you want, and also make sure you attach it to a particular value so the animation triggers only when that specific value changes.

How do I animate a view in SwiftUI?

If you want a SwiftUI view to start animating as soon as it appears, you should use the onAppear() modifier to attach an animation.


1 Answers

You change the color, but animating view, which is set up forever is not changed - it remains as set and continues as specified - forever. So it needs to re-set the animation.

Please find below a working full module demo code (tested with Xcode 11.2 / iOS 13.2). The idea is to use ObservableObject view model as it allows and refresh view and perform some actions on receive. So receiving color changes it is possible to reset and view color and animation.

Updated for Xcode 13.3 / iOS 15.4

demo

Main part is:

    }
    .onAppear { self.animate = true }
    .animation(animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : .default, value: animate)
    .onChange(of: viewModel.colorIndex) { _ in
        self.animate = false                     // << here !!
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            self.animate = true                  // << here !!
        }
    }

Complete findings and code is here

like image 116
Asperi Avatar answered Sep 21 '22 14:09

Asperi