Not only CGPath
is opaque, but also CAAnimation
doesn't support any updates or notifications for ongoing animations (i.e. after started but before finished). The only entities involved are animation itself and CALayer
-s it is applied to.
So, options are:
(some options may sound too scary but they are not, so I made an example project, see below)
repeatCount
As wj2061 mentioned is his answer you can tweak animation's repeatCount
. Cons is it will animate 0.25 of animation time, not 0.25 of path
CAShapeLayer
If, by any chance, you can represent your ticker
with CAShapeLayer
segment then you can animate strokeStart
and strokeEnd
so it will look like segment is moving along the path
Clever repeatCount
You can calculate such repeatCount
value that animation will stop at 0.25 of path.
- grab some bezier lib
- extract bezier from timing function with
getControlPointAtIndex:
- solve bezier to get its "progress value" (usually named
t
) for which bezier's 'y' value will match to your "required progress" (0.25)
- calculate bezier's 'x' value for that
t
- this is exact value of repeatCount
you need
Animating with CAAnimation, all by yourself
kind of advanced
- grab some bezier lib
- create custom CALayer subclass with dynamic property, let's say
rideProgress
- add synthesized properties for bezier path (from bezier lib, not CGPath) and sublayer (say,
rideLayer
) to animate
- override
needsDisplayForKey:
for rideProgress
key and initWithLayer:
for all introduced properties BUT use self.rideLayer?.presentationLayer()
instead of copying rideLayer
- override one of these:
drawInContext:
and draw what you need in it; or (better) display
, in display
retrieve current rideProgress
value from presentationLayer
and update sublayer, then call super. Either way, use bezier lib to calculate position and rotation for sublayer accordingly to current rideProgress
value
- don't forget to
CATransaction.setDisableActions(true)
before setting any animatable property of any layer
- finally, use any kind of CAAnimation or implicit animation on
rideProgress
property
Split path
Again, suggested by wj2061. You can split the path so one of halves will represent 0.25 of original
Here is example implementation of everything above EXCEPT "Split path". I didn't run any field tests on this code, it's just a working concept. XCode 7.3.1, Swift.
Materials used: Wiki on Cubic function, Great article about operations on beziers, Cubic equations solving method line-by-line
kCAMediaTimingFunctionEaseInEaseOut
timing function and 0.25 for therepeatCount
, the animation will stop sooner than expected. Furthermore, the timing function will still be applied to the entire animation's duration – and therefore it'll appear to speed up and then suddenly stop, which may or may not be what OP wants. – Pedicure