How to animate only a percentage of the full CALayer animation along UIBezierPath?

I managed to animate CALayer along the UIBezierPath.

What I'm trying to accomplish is to revive only a percentage of the path, for example, only 25% of the path, and the layer remains in this position (25%).

What is the way to do this? Here is my code, it always animates the full path.

let aPath = UIBizierPath(CGPath: somePath) let anim = CAKeyframeAnimation(keyPath: "position") anim.path = aPath.CGPath anim.rotationMode = kCAAnimationRotateAuto anim.repeatCount = 1 anim.fillMode = kCAFillModeForwards anim.removedOnCompletion = false anim.duration = 3.0 anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) ticker.addAnimation(anim, forKey: "animate_ticker") 
+8
ios caanimation cakeyframeanimation
source share
4 answers

Simple change of one property:

 anim.repeatCount = 0.25 

Here's a great article on animation time , you can learn how to have even finer control over the animation.

Append:
1. To achieve what you want, the closest way is to have a 25% subpacket, here is some kind of helper method .

2. If you can withstand the difference in speed, use the method described above and return the position after the end of the animation:

 ticker.position = ticker.presentationLayer().position 
+2
source share

Have you tried setting the fromValue and toValue properties ? It should work if you set fromValue to 0.0 and toValue to 0.25

0
source share

Not only is CGPath opaque, but CAAnimation also does not support any updates or notifications for current animations (i.e. after launch, but before completion). The only objects involved are the animation itself and the CALayer -s to which it applies.

So, the options are:

(some parameters may seem too scary, but this is not so, so I made an example project, see below)

RepeatCount

As wj2061 mentioned, its answer , you can customize the repeatCount animation. Cons will animate 0.25 animation times, not 0.25 paths

CAShapeLayer

If you can imagine your ticker with a CAShapeLayer segment, then you can animate strokeStart and strokeEnd to make it look like the segment is moving along the path

Smart repeatCount

You can calculate a repeatCount such that the animation stops at a 0.25 path.

  • grab some bezier lib
  • extract bezier from a synchronization function using getControlPointAtIndex:
  • decide bezier to get its "progress value" (usually called t ) for which the bezier 'y' value will match your "desired progress" (0.25)
  • compute the bezier value 'x' for that t - this is the exact repeatCount value you need

Animation with CAAnimation, all by yourself

extended view

  • grab some bezier lib
  • create a custom subclass of CALayer with a dynamic property, say rideProgress
  • add synthesized properties for the bezier path (from bezier lib, not CGPath) and a sublayer (e.g. rideLayer ) for animation
  • override needsDisplayForKey: for rideProgress and initWithLayer: for all entered properties. Use self.rideLayer?.presentationLayer() instead of copy rideLayer
  • override one of the following: drawInContext: and draw what you need; or (better) display , in display extract the current rideProgress value from the presentationLayer and update the sublayer, then call super. In any case, use bezier lib to calculate the position and rotation of the sublayer according to the current rideProgress value
  • don't forget CATransaction.setDisableActions(true) before setting any animated property of any level
  • finally, use any kind of CAAnimation or implicit animation in the rideProgress property

Split path

Again, suggested by wj2061 . You can split the path so that one half represents 0.25 of the original


Here is an example implementation of all the above EXCEPT "Split path". I have not conducted any field testing of this code, this is just a working concept. Xcode 7.3.1, Swift.


Materials used: Wiki on Cubic function , Excellent article on operation without beziers , Method for solving cube equations in turn

0
source share

I ran into the same problem, and I wanted to animate the drawing of the path, but only a percentage of it.

What I ended up with was setting the strokeStart and strokeEnd levels for the same floating point values ​​as the animation.

So, in your example, try setting anim.fromValue = 0.0f , anim.toValue = 0.6f, as well as ticker.strokeStart=0.0f and ticker.strokeEnd = 0.6f .

It successfully attracted only 60% of the way and animated it!

0
source share

All Articles