NilsH
NilsH

Reputation: 13821

Starting animation at a given offset

Is there a way to achieve what the timeOffset property of an animation does, starting the animation at some point in time, but without the "wrapping" behaviour?

I have two animations (in two different layers):

// This is the animation of the stroke of a circle
let progressAnim = CABasicAnimation(keyPath: "strokeEnd")
progressAnim.duration = duration
progressAnim.fromValue = 0
progressAnim.toValue = 1
progressAnim.fillMode = kCAFillModeBackwards
progressAnim.timeOffset = elapsed

// This is the animation of a pointer that follow the same circle as above
let arrowAnim = CAKeyframeAnimation(keyPath: "position")
arrowAnim.duration = duration
arrowAnim.rotationMode = kCAAnimationRotateAuto
arrowAnim.path = arrowPath.CGPath
arrowAnim.fillMode = kCAFillModeBackwards
arrowAnim.timeOffset = elapsed

This starts the animations at the wanted progress, but when it reaches what is supposed to the the end, it starts over and lasts for the remaining duration. I realize this is how timeOffset is specified to work, but I was hoping that it is possible to somehow achieve the same without the wrap.

Upvotes: 0

Views: 754

Answers (3)

NilsH
NilsH

Reputation: 13821

I think I figured it out. By trial and error, it seems to work when I set beginTime of the animation to a time in the past, like this:

let beginTime = CACurrentMediaTime() - offset
// Set the beginTime of the progress animation
progressAnim.beginTime = beginTime
// Set the begintTime of the arrow animation
arrowAnim.beginTime = beginTime

This seems to have the desired effect.

Upvotes: 1

Duncan C
Duncan C

Reputation: 131418

Yes, it's possible. You'll need to use the same settings that you use to pause and resume an "in-flight" animation. The documentation is pretty weak, and the properties of the animation are confusing as hell. Every time I have to work with pausing and resuming animation I have to spend like half a day figuring it out again, and then a week later, I've forgotten how to do it again. It's been at least 6 months since I've dealt with it, so I really forget how to do it.

I have a demo project on github that shows how to pause and resume an animation, and even to use a slider to move an animation forward and backward. I suggest you take a look at that. It has all the pieces you need:

Keyframe view animation demo on Github

Upvotes: 1

Mundi
Mundi

Reputation: 80265

Instead of the timeOffset hack, you can calculate the proper fromValue and corresponding duration.

e.g.

progressAnim.duration = duration - elapsed
progressAnim.fromValue = elapsed / duration

Upvotes: 1

Related Questions