Search code examples
iosswiftanimationcaanimation

How can I create an iOS CAAnimation and define every interpolated value myself?


I want to animate the path of a CAShapeLayer. However, this path is created using many arcs. The number of arcs is the same in the begin and end value of the path. However, since the arcs are of different length, this seems to mean that the actual paths use a different amount of Bezier Control Points. This means that the animation is not predictable and very glitchy*.

My solution so far is to create a CAKeyFrameAnimation, and put in a very high number of keyframes. It only works with a very high number of keyframes per second. (around 200 to 300). Anything lower, and glitches* start to appear.

This approach is very crude as it succes depends on the actual frame rate on the actual device and creates more instances of the key frames than is actually needed for the animation, wasting memory. So my question is: Is there a way to create an animation where I have to create every value somehow? I am immagining some delegate based approach where I am asked a value based on a key time. I don't know what the best approach is to my problem.

*Note: The glitches I am speaking of are weirdly looking paths that appear for one frame only.


Solution

  • You should try using a CADisplayLink

    Here is an example:

    func setupAnimation() {
        let dispLink = CADisplayLink(target: self, selector: #selector(updateAnimation))
        dispLink.preferredFramesPerSecond = 60 //will update 60 times per second (the default for iOS devices) ... this line of code is optional depending on the fps you want for your animation
        dispLink.add(to: RunLoop.current, forMode: RunLoop.Mode.common)
    }
    
    func updateAnimation() {
        //do your animation code here
    }
    

    Using a display link will link your animation to the refresh rate of the screen that way it's smooth and you can basically do anything you want without it looking choppy