This article focuses on how to pause and continue CALayer’s animation. Let’s start with CALayer.

/** The base layer class. **/

@interface CALayer : NSObject <NSCoding, CAMediaTiming>
Copy the code

NSCoding is more commonly used, so I won’t go into that. So what is a CAMediaTiming?!

CAMediaTiming

/* The CAMediaTiming protocol is implemented by layers and animations, it
 * models a hierarchical timing system, with each object describing the
 * mapping from time values in the object's parent to local time. * * Absolute time is defined as mach time converted to seconds. The * CACurrentMediaTime function is provided as a convenience for querying the * current absolute time. * * The conversion from parent time to local time has two stages: * * 1. conversion to "active local time". This includes the point at * which the object appears in the parent's timeline, and how fast it
 * plays relative to the parent.
 *
 * 2. conversion from active to "basic local time". The timing model
 * allows for objects to repeat their basic duration multiple times,
 * and optionally to play backwards before repeating. */
Copy the code

CALayer inherits the CAMediaTiming protocol, which allows time conversion between layer and its parent. That is, the animation time on the layer can be converted to the actual time. The steps of transformation are also clearly described. So what does this conversion mean?

CAMediaTiming contains a lot of attributes. IOS attributes for protocol have no instance variables, just getters/setters. This is similar to a category: adding attributes to a category only adds getter/setter methods, not actual instance variables. Because categories are determined at Runtime. When instance variables are added, the memory space of the class object is changed. The memory space of class objects is determined at compile time. So you can’t add instance variables to a category, but the getters/setters for the properties are still valid, and the same is true for protocol. Welcome to discuss if there is any inaccuracy in my understanding of this point.

@protocol CAMediaTiming

/* The begin time of the object, in relation to its parent object, if
 * applicable. Defaults to 0. */

@property CFTimeInterval beginTime;

/* The basic duration of the object. Defaults to 0. */

@property CFTimeInterval duration;

/* The rate of the layer. Used to scale parent time to local time, e.g.
 * if rate is 2, local time progresses twice as fast as parent time.
 * Defaults to 1. */

@property float speed;

/* Additional offset in active local time. i.e. to convert from parent
 * time tp to active local time t: t = (tp - begin) * speed + offset.
 * One use of this is to "pause" a layer by setting `speed' to zero and * `offset' to a suitable value. Defaults to 0. */

@property CFTimeInterval timeOffset;

/* The repeat count of the object. May be fractional. Defaults to 0. */

@property float repeatCount;

/* The repeat duration of the object. Defaults to 0. */

@property CFTimeInterval repeatDuration;

/* When true, the object plays backwards after playing forwards. Defaults
 * to NO. */

@property BOOL autoreverses;

/* Defines how the timed object behaves outside its active duration.
 * Local time may be clamped to either end of the active duration, or
 * the element may be removed from the presentation. The legal values
 * are `backwards', `forwards', `both' and `removed'. Defaults to
 * `removed'. */ @property(copy) NSString *fillMode; @endCopy the code

See the familiar Duration and Autoreverses, which turned out to be in CAMediaTiming. Originally thought to be CALayer’s own attribute… What are the other key attributes, beginTime, Speed, timeOffset?

  • BeginTime: Start time of the object that inherits the CAMediaTiming protocol, which is related to the parent object. What the hell? It’s not clear…
  • Speed: indicates the ratio between the local time and parent time. The default value is 1. For example, when speed is 2, local time is twice as fast as parent time.
  • TimeOffset: timeOffset, which is more difficult to understand. The offset used to convert between local time and parent time.

Still not sure how to use CAMediaTiming and its attributes after reading these comments, look at an example below. These related properties are introduced very concisely by pausing the animation and continuing the animation.

Start the animation

[UIView animateWithDuration: 2.0 animations: ^ {the view1. Frame = CGRectMake (self. View. Frame. The size, width - 100, 100, 100, 100);  } completion:^(BOOL finished) { }];Copy the code

Suspended animation

- (void)demosAnimationPause:(UIButton *)sender {// convert the current time CACurrentMediaTime to the time on the layer, i.e. parent time tolocaltime CFTimeInterval pauseTime = [view1.layer convertTime:CACurrentMediaTime() fromLayer:nil]; View1.layer. timeOffset = pauseTime; view1.layer.timeOffset = pauseTime; //localThe ratio of time to parent time is 0, meaninglocalTime suspends view1.layer.speed = 0; }Copy the code

One use of this is to “pause” a layer by setting speed to zero and offset to a suitable value.

Pausing an animation is actually quite simple.

Continue to animation

- (void)demosAnimationContinue (UIButton *) Sender {CFTimeInterval pauseTime = view1.layer.timeOffset; CFTimeInterval timeSincePause = CACurrentMediaTime() -pausetime; // Cancel view1.layer.timeOffset = 0; //localTime relative to parent time world beginTime view1.layer.beginTime = timeSincePause; // continue view1.layer.speed = 1; }Copy the code

So how do you continue with the animation? Set local time beginTime and speed again. In fact, the most difficult thing to understand is the conversion relationship between local time and parent time.

Demo

For Demo, see ios-Animation