CAMediaTiming 'Protocol (9.1 layer time), camediatiming9.1

Source: Internet
Author: User

CAMediaTiming 'Protocol (9.1 layer time), camediatiming9.1

# CAMediaTiming Protocol

CAMediaTimingThe Protocol defines a set of attributes used to control the elapsed time in an animation,CALayerAndCAAnimationThis Protocol is implemented, so the time can be controlled by any class based on a layer or an animation.

Persistence and repetition

We mentioned in chapter 8 "Explicit Animation"duration(CAMediaTiming),durationIsCFTimeInterval(SimilarNSTimeIntervalA double-precision floating point type), specifies the time for an iteration of the animation to be executed.

HereOne IterationWhat does that mean?CAMediaTimingAnother attribute is calledrepeatCountThe number of iterations of the animation. IfdurationIs 2,repeatCountSet it to 3.5 (three semi-iterations), and the complete animation duration will be 7 seconds.

durationAndrepeatCountThe default value is 0. However, this does not mean that the animation duration is 0 seconds, or 0 times. Here 0 only represents the "default", that is, 0.25 seconds and 1 time, you can use a simple test to assign multiple values to these two attributes, for example, listing 9.1 and Figure 9.1 show the program results.

List 9.1 TestdurationAndrepeatCount

 1 @interface ViewController () 2  3 @property (nonatomic, weak) IBOutlet UIView *containerView; 4 @property (nonatomic, weak) IBOutlet UITextField *durationField; 5 @property (nonatomic, weak) IBOutlet UITextField *repeatField; 6 @property (nonatomic, weak) IBOutlet UIButton *startButton; 7 @property (nonatomic, strong) CALayer *shipLayer; 8  9 @end10 11 @implementation ViewController12 13 - (void)viewDidLoad14 {15     [super viewDidLoad];16     //add the ship17     self.shipLayer = [CALayer layer];18     self.shipLayer.frame = CGRectMake(0, 0, 128, 128);19     self.shipLayer.position = CGPointMake(150, 150);20     self.shipLayer.contents = (__bridge id)[UIImage imageNamed: @"Ship.png"].CGImage;21     [self.containerView.layer addSublayer:self.shipLayer];22 }23 24 - (void)setControlsEnabled:(BOOL)enabled25 {26     for (UIControl *control in @[self.durationField, self.repeatField, self.startButton]) {27         control.enabled = enabled;28         control.alpha = enabled? 1.0f: 0.25f;29     }30 }31 32 - (IBAction)hideKeyboard33 {34     [self.durationField resignFirstResponder];35     [self.repeatField resignFirstResponder];36 }37 38 - (IBAction)start39 {40     CFTimeInterval duration = [self.durationField.text doubleValue];41     float repeatCount = [self.repeatField.text floatValue];42     //animate the ship rotation43     CABasicAnimation *animation = [CABasicAnimation animation];44     animation.keyPath = @"transform.rotation";45     animation.duration = duration;46     animation.repeatCount = repeatCount;47     animation.byValue = @(M_PI * 2);48     animation.delegate = self;49     [self.shipLayer addAnimation:animation forKey:@"rotateAnimation"];50     //disable controls51     [self setControlsEnabled:NO];52 }53 54 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag55 {56     //reenable controls57     [self setControlsEnabled:YES];58 }59 60 @end
View Code

Figure 9.1 demodurationAndrepeatCountTest Program

Another way to create a duplicate animation is to userepeatDurationAttribute, which allows the animation to repeat a specified time, rather than a specified number of times. You even setautoreversesAttributes (BOOL type) are automatically played back during the alternating cycle of each interval. This is useful for playing a continuous, non-repeating animation, such as opening a door and closing it (Figure 9.2 ).

 

Figure 9.2 swing door Animation

The code for swinging the door can be found in listing 9.2. We usedautoreversesTo automatically close the door after it is opened.repeatDurationSetINFINITYSo the animation can be played infinitely and setrepeatCountIsINFINITYIt also has the same effect. Note:repeatCountAndrepeatDurationThey may conflict with each other, so you only need to specify a non-zero value for one of them. The behavior of setting non-0 values for both attributes is not defined.

Usage in listing 9.2autoreversesSwing of attribute Implementation door

 

@interface ViewController ()@property (nonatomic, weak) UIView *containerView;@end@implementation ViewController- (void)viewDidLoad{    [super viewDidLoad];    //add the door    CALayer *doorLayer = [CALayer layer];    doorLayer.frame = CGRectMake(0, 0, 128, 256);    doorLayer.position = CGPointMake(150 - 64, 150);    doorLayer.anchorPoint = CGPointMake(0, 0.5);    doorLayer.contents = (__bridge id)[UIImage imageNamed: @"Door.png"].CGImage;    [self.containerView.layer addSublayer:doorLayer];    //apply perspective transform    CATransform3D perspective = CATransform3DIdentity;    perspective.m34 = -1.0 / 500.0;    self.containerView.layer.sublayerTransform = perspective;    //apply swinging animation    CABasicAnimation *animation = [CABasicAnimation animation];    animation.keyPath = @"transform.rotation.y";    animation.toValue = @(-M_PI_2);    animation.duration = 2.0;    animation.repeatDuration = INFINITY;    animation.autoreverses = YES;    [doorLayer addAnimation:animation forKey:nil];}@end
View Code relative time

Each time we talk about Core Animation, the time is relative. Each Animation has its own time, which can be accelerated, delayed, or offset independently.

beginTimeSpecifies the delay time before the animation starts. The latency starts from the moment the animation is added to the visible layer. The default value is 0 (that is, the animation will be executed immediately ).

speedIs a multiple of time. The default value is 1.0. Reducing it will slow down the layer/animation time, and increasing it will speed up. If the speed is 2.0durationThe animation with a value of 1 has actually been completed in 0.5 seconds.

timeOffsetAndbeginTimeSimilarbeginTimeThe delay animation is different.timeOffsetJust let the animation go to a certain point. For example, for an animation that lasts for 1 second, SettimeOffset0.5 means that the animation starts in half.

AndbeginTimeThe difference is that,timeOffsetNot Affectedspeed. So if youspeedSet it to 2.0timeOffsetIf the animation is set to 0.5, the animation starts from the end of the animation, because the animation within one second is actually reduced to 0.5 seconds. HowevertimeOffsetLet the animation start from the end, and it still plays a full length. This animation is just a loop and then played from the beginning.

You can use the test program in listing 9.3 to verify and setspeedAndtimeOffsetSlider to the random value, and then click play to observe the effect (see Figure 9.3)

List 9.3 TesttimeOffsetAndspeedAttribute

 

 1 @interface ViewController () 2  3 @property (nonatomic, weak) IBOutlet UIView *containerView; 4 @property (nonatomic, weak) IBOutlet UILabel *speedLabel; 5 @property (nonatomic, weak) IBOutlet UILabel *timeOffsetLabel; 6 @property (nonatomic, weak) IBOutlet UISlider *speedSlider; 7 @property (nonatomic, weak) IBOutlet UISlider *timeOffsetSlider; 8 @property (nonatomic, strong) UIBezierPath *bezierPath; 9 @property (nonatomic, strong) CALayer *shipLayer;10 11 @end12 13 @implementation ViewController14 15 - (void)viewDidLoad16 {17     [super viewDidLoad];18     //create a path19     self.bezierPath = [[UIBezierPath alloc] init];20     [self.bezierPath moveToPoint:CGPointMake(0, 150)];21     [self.bezierPath addCurveToPoint:CGPointMake(300, 150) controlPoint1:CGPointMake(75, 0) controlPoint2:CGPointMake(225, 300)];22     //draw the path using a CAShapeLayer23     CAShapeLayer *pathLayer = [CAShapeLayer layer];24     pathLayer.path = self.bezierPath.CGPath;25     pathLayer.fillColor = [UIColor clearColor].CGColor;26     pathLayer.strokeColor = [UIColor redColor].CGColor;27     pathLayer.lineWidth = 3.0f;28     [self.containerView.layer addSublayer:pathLayer];29     //add the ship30     self.shipLayer = [CALayer layer];31     self.shipLayer.frame = CGRectMake(0, 0, 64, 64);32     self.shipLayer.position = CGPointMake(0, 150);33     self.shipLayer.contents = (__bridge id)[UIImage imageNamed: @"Ship.png"].CGImage;34     [self.containerView.layer addSublayer:self.shipLayer];35     //set initial values36     [self updateSliders];37 }38 39 - (IBAction)updateSliders40 {41     CFTimeInterval timeOffset = self.timeOffsetSlider.value;42     self.timeOffsetLabel.text = [NSString stringWithFormat:@"%0.2f", timeOffset];43     float speed = self.speedSlider.value;44     self.speedLabel.text = [NSString stringWithFormat:@"%0.2f", speed];45 }46 47 - (IBAction)play48 {49     //create the keyframe animation50     CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];51     animation.keyPath = @"position";52     animation.timeOffset = self.timeOffsetSlider.value;53     animation.speed = self.speedSlider.value;54     animation.duration = 1.0;55     animation.path = self.bezierPath.CGPath;56     animation.rotationMode = kCAAnimationRotateAuto;57     animation.removedOnCompletion = NO;58     [self.shipLayer addAnimation:animation forKey:@"slide"];59 }60 61 @end
View Code

Figure 9.3 simple application to test time offset and speed

FillMode

ForbeginTimeFor a non-zero animation, a State appears when the animation is added to the layer but nothing happens. Similarly,removeOnCompletionSetNOThe animation will remain in the previous State at the end of the animation. This creates a problem. Before and after the animation starts, what is the value of the property of the animation to be set?

One possibility is that the attributes are consistent with the animation before being added, that is, the value defined in the model layer (See Chapter 7 "implicit Animation", model layer and rendering layer interpretation ).

Another possibility is to keep the frame before the animation starts, or the frame after the animation ends. This is the so-calledFillBecause the animation start and end values are used to fill in the time before and after the start.

This behavior is handed over to the developer, and it can beCAMediaTimingOffillModeTo control.fillModeIsNSStringType. The following four constants are acceptable:

kCAFillModeForwards kCAFillModeBackwards kCAFillModeBoth kCAFillModeRemoved

The default value iskCAFillModeRemovedWhen the animation is no longer played, the remaining three types of values specified by the layer model are displayed, either backward or backward, filling the animation status, this allows the animation to remain the starting and ending values before or after the animation.

This provides another solution to avoid returning quickly when the animation ends (see Chapter 8 ). But remember, when you use it to solve this problem, you needremoveOnCompletionSetNOIn addition, you need to add a non-empty key to the animation, so you can remove it from the layer when no animation is required.

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.