How to stop an animation

(swift, storyboards, macOS)

Can I stop or pause an animation?

(I could find how to remove it: view1.layer?.removeAllAnimations()

Here is the official documentation but I do not understand: https://developer.apple.com/documentation/uikit/uiviewanimating/1649843-pauseanimation)

    @IBAction func fadeOut(_ sender: NSButton) {
        NSAnimationContext.runAnimationGroup({ (context) in
            context.duration = 5.0
            view1.animator().alphaValue = 0
        })
    }

Replies

You can do this (I added print to see what's happening:

    @IBAction func startAnimation(_ sender: NSButton) {
        NSAnimationContext.runAnimationGroup({ (context) in
            print("Start", view1.alphaValue)
            context.duration = 5.0
            view1.animator().alphaValue = 0
            print("End", view1.alphaValue)
        }) { // Completion
            print("Completed", self.view1.alphaValue)
            self.view1.alphaValue = 1.0  // You may need to reset at the end ?
        }
    }
    
    @IBAction func stopAnimation(_ sender: NSButton) {
        print("Stop")
        view1.layer?.removeAllAnimations()
    }

When you stop, animation ends immediately and completion handler is called.

Hope that helps.

  • As I said in my question I already have done that. I am asking how to "pause" or stop the animation not how to "remove".

    When I use removeAllAnimations, view1 goes to alphaValue = 1 (in your example)

    I want to click stop/pause and the animation stop at that point, at some % between 0 and 1 alphaValue. Perhaps at 0.3 or 0.5 or whatever it is when the user click to stop/pause

Add a Comment

I want to click stop/pause and the animation stop at that point, at some % between 0 and 1 alphaValue

I have not found a direct way to do it. But here is a workaround.

At start of animation:

  • get the alphaValue: initAlpha
  • get the time

In the completion, if elapsed is less than the set duration (here 5.0), which means animation was stopped:

  • compute elapsedTime since beginning of animation
  • compute what should be alpha at this time, if "normal" endValue (0) is endAlpha and normalDuration (5.0):
let deltaAlpha = (initAlpha - endAlpha) * (elapsed / normalDuration)
  • and set alpha inaccordingly:
self.view1.alphaValue = initAlpha - deltaAlpha

Full code should look like this:

    @IBAction func startAnimation(_ sender: NSButton) {
        let initAlpha = self.view1.alphaValue // Usually 1.0
        let endAlpha = CGFloat(0)
        let startTime = DispatchTime.now()  // Precisely when animation starts
        let fixedDuration = 5.0
        var elapsedTime : Double = 0.0

        NSAnimationContext.runAnimationGroup({ (context) in
            context.duration = fixedDuration // 5.0
            self.view1.animator().alphaValue = endAlpha // 0
        }) { // Completion
            let endTime = DispatchTime.now()
            elapsedTime = Double((endTime.uptimeNanoseconds - startTime.uptimeNanoseconds)) / 1_000_000_000 // Difference in seconds

            if elapsedTime >= fixedDuration {
                self.view1.alphaValue = initAlpha // return to initial value 1.0
            } else {        // Adjust proportionally
                let deltaAlpha = (initAlpha - endAlpha) * (elapsedTime / fixedDuration)
                self.view1.alphaValue = initAlpha - deltaAlpha
            }
        }
    }
  • Thank you!

  • Does that do the job ?

  • Documentation for stop() explains that when stopped, animation goes to the end, not at "where it is". The current progress of the receiver is not reset. When this method is sent to instances of NSViewAnimation (a subclass of NSAnimation) the receiver moves to the end frame location.

Add a Comment

Did you manage to stop the animation with this solution ?