好东西小知识点iOS Developer

给iOS图层添加动画

2017-03-24  本文已影响498人  熊妹妹

核心动画可以在layer上创造复杂的动画,比如修改大小、位置、旋转变换等等,也可以同时修改一个或多个属性。

简单修改layer属性做动画

首先理解下隐式动画和显示动画。当修改图层任意属性时都会出发隐式动画,隐式动画有默认时间步调和其他属性。如果不使用系统的默认动画可以通过创建CABasicAnimation对象指定图层的显示动画。调用addAnimation:forKey:方法把动画添加到图层上

在之前的矢量图上添加一个缩放的动画

CAShapeLayer *layer1 = [CAShapeLayer layer];
layer1.bounds = CGRectMake(0, 0, 200, 200);
layer1.position = self.view.center;
layer1.backgroundColor = [UIColor colorWithRed:0.9 green:0.3 blue:0.3 alpha:0.3].CGColor;
    
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 0)];
[path addCurveToPoint:CGPointMake(0, 50)
       controlPoint1:CGPointMake(50, 25)
       controlPoint2:CGPointMake(25, 50)];
    
[path addCurveToPoint:CGPointMake(-50, 0)
       controlPoint1:CGPointMake(-25, 50)
       controlPoint2:CGPointMake(-50, 25)];
    
[path addCurveToPoint:CGPointMake(0, -50)
       controlPoint1:CGPointMake(-50, -25)
       controlPoint2:CGPointMake(-25, -50)];
    
[path addCurveToPoint:CGPointMake(50, 0)
       controlPoint1:CGPointMake(25, -50)
       controlPoint2:CGPointMake(50, -25)];
CGAffineTransform transform = CGAffineTransformMakeTranslation(100, 100);
[path applyTransform:transform];
    
layer1.path = path.CGPath;
layer1.fillColor = [UIColor whiteColor].CGColor;
layer1.strokeColor = [UIColor blueColor].CGColor;
    
[self.view.layer addSublayer:layer1];
    
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.5, 1.5, 1)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.2, 0.2, 1)];
animation.duration = 4.0;
[layer1 addAnimation:animation forKey:@"animation1"];

<img src="https://img.haomeiwen.com/i1840221/e8152fe11bd3915a.gif?imageMogr2/auto-orient/strip" width=250>

要注意,显式动画只是提供一个动画,它并不会修改图层对象的数据。所以在动画结束时,需要更新图层对象的数据。

动画会在runloop结束时开始执行,因此当前线程必须要有一个runloop才可以让动画执行。即便改变图层的多个属性或是添加多个动画,他们都会在同一时刻执行。比如你可以在移动的时候同时修改图层的不透明度。虽然他们是同时执行的,但是你可以单独配置每个属性的动画对象,控制他们属性变化的时间节奏。

用关键帧动画修改layer属性

关键帧动画可以在一个动画周期内给属性设置多个值。关键帧动画由一系列的值和每两个值之间变化时的时间节奏组成,他们都用数组表示。

CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
keyframeAnimation.keyTimes = @[@(0),@(0.3),@(0.5),@(1)];
keyframeAnimation.values = @[[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.5, 1.5, 1)],
                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.2, 1.2, 1)],
                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 0.2, 1)],
                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.3, 1.2, 1)]];
keyframeAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
keyframeAnimation.duration = 8.f;
keyframeAnimation.fillMode = kCAFillModeForwards;
keyframeAnimation.removedOnCompletion = NO;
[layer1 addAnimation:keyframeAnimation forKey:@"transform2"];

<img src="https://img.haomeiwen.com/i1840221/e58e4631a46e29fd.gif?imageMogr2/auto-orient/strip" width=250>

动画属性keyPath

在第一行创建关键帧动画时调用方法animationWithKeyPath,并传入动画属性keypath。CAPropertyAnimation定义了动画的属性值,它支持很多属性,具体可以查阅官方文档。

关键帧的值

通过动画的path或values来设置关键帧的值。属性是CGPoint类型的(锚点或位置)通常用动画的path属性来设置,path是CGPathRef类型。也可以用values属性来设置,它是数组类型。这时需要把CGPoint类型用NSValue来进行封装再添加到数组中,同样的CATransform3D和CGRect类型用NSValue封装、 CGFloat类型用NSNumber封装。

关键帧之间的节奏

关键帧动画的时间节奏和插值是通过一系列属性共同控制的:

动画协议

你会发现第一个demo动画结束时,layer回到了初始状态,而第二个demo在开始和结束时layer保持动画开始和结束的状态。因为我设置了fillMode和removedOnCompletion这两个属性。layer的transform值始终都是CATransform3DIdentity,但是设置了这两个属性后可以让图层动画开始时就渲染到CATransform3DMakeScale(1.5, 1.5, 1),结束时渲染到CATransform3DMakeScale(0.3, 1.2, 1)。

CAMediaTiming协议是一套抽象接口,描述了动画的一些信息,CALayer和CAAnimation都实现了该协议

removedOnCompletion是CAAnimation的属性,它表示动画一旦结束渲染就停止,所以第一个demo看到动画结束时layer又变回了初始的样子。

运行时停止动画

动画通常会一直运行到结束,如果想提前中止有两种方法:

当从图层移除一个动画的时候,会出发图层的重新绘制。图层会跳跃到动画之前状态,如果想保持最后一帧的状态可以通过修改图层属性实现。

动画组合

如果想图层一直执行多个动画,可以创建CAAnimationGroup对象通过配置animations属性来实现。动画组的的事件节奏和时长属性会覆盖掉所包含的动画属性。

检测动画结束

当动画开始和结束时,可以通过回调得知:

如果你想连接两个动画尽量不要用这种方式,通过设置动画的beginTime来实现。

上一篇 下一篇

猜你喜欢

热点阅读