This paper demonstrates the use of cabasic animation and the principle of interactive animation through an example.
First, let's look at the final effect:
The head image changes from rectangle animation to circle. The whole process can be controlled by finger movement. Let's implement it step by step, let's GO!
First of all, I will give an example of a avatar layer:
float w = 120.0; self.headerLayer = [CALayer layer]; self.headerLayer.frame = CGRectMake(0, 0, w, w); self.headerLayer.position = CGPointMake((200 - w) / 2, (200 - w) / 2); self.headerLayer.anchorPoint = CGPointMake(0, 0.5); self.headerLayer.contents = (__bridge id)[UIImage imageNamed:@"head.jpg"].CGImage; self.headerLayer.masksToBounds = YES; self.headerLayer.cornerRadius = 0.0; [self.containerView.layer addSublayer:self.headerLayer];
In this case, the corner trimming is mainly done by corneraradius, which is initialized to have no corner.
Next, set the animation. Before the animation, pause the animation, or it will play automatically after the animation is set:
self.headerLayer.speed = 0.0;
Because our animation includes fillet transformation and translation along the y axis, these two animations are under the control of translation gesture. We use the way of combination animation to achieve:
CABasicAnimation *animation = [CABasicAnimation animation]; animation.keyPath = @"cornerRadius"; animation.toValue = @(w / 2); animation.duration = 1.0; CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position.y"]; positionAnimation.toValue = @(self.headerLayer.position.y - w); positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; CAAnimationGroup *animaGroup = [CAAnimationGroup animation]; animaGroup.duration = 2.0f; animaGroup.fillMode = kCAFillModeForwards; animaGroup.removedOnCompletion = NO; animaGroup.animations = @[animation, positionAnimation]; [self.headerLayer addAnimation:animaGroup forKey:@"Animation"];
Finally, we set up gesture processing:
- (void)pan:(UIPanGestureRecognizer *)pan { CGFloat x = [pan translationInView:self.view].x; x /= 200.0f; CFTimeInterval timeOffset = self.headerLayer.timeOffset; timeOffset = MIN(0.999, MAX(0.0, timeOffset - x)); self.headerLayer.timeOffset = timeOffset; self.titleLabel.layer.timeOffset = timeOffset; [pan setTranslation:CGPointZero inView:self.view]; }
The key of manual interaction is to control the timeOffset of the layer, which can control the time offset of the current animation execution, ranging from 0 to 1, so we need to make a conversion between the position of the mobile gesture and the time point of the animation. In addition, pay attention to reset the gesture to ensure that the offset position (x) relative to the last time can be obtained each time.