iOS 动画基础总结篇
动画的大体分类(个人总结可能有误)
分类.png
UIView 动画
属性动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [UIView beginAnimations:nil context:nil]; [UIView setAnimationDelay: 1 ]; [UIView setAnimationDuration: 2 ]; [UIView setAnimationRepeatCount: 100 ]; [UIView setAnimationRepeatAutoreverses: YES]; // 翻转 [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; //设置动画变化的曲线 UIView *view = self.redview; view.alpha = 0 ; view.center = CGPointMake(view.center.x + 300 , view.center.y); [UIView setAnimationDelegate:self]; // 设置代理 监测动画结束的 [UIView setAnimationDidStopSelector:@selector(shopAction)]; [UIView commitAnimations]; 其中 setAnimationCurve 参数为 UIViewAnimationCurveEaseInOut:这种曲线的动画开始缓慢,在其持续时间的中间加速,然后在完成之 前再次减慢。这是大多数动画的默认曲线。 UIViewAnimationCurveEaseIn:动画开始时缓慢,然后加速,直到动画结束。这里选用这种类型动画曲 线。 UIViewAnimationCurveEaseOut:动画开始时速度很快,在结束前开始减速。 UIViewAnimationCurveLinear:在动画持续时间内,动画匀速运行。 |
基于Block的属性动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | [UIView animateWithDuration: 0.5 animations:^{ UIView *view = self.viewArray[ 4 ]; view.transform = CGAffineTransformRotate(view.transform, M_2_PI); // 顺时针旋转 }]; [UIView animateKeyframesWithDuration: 2 delay: 0 options:UIViewKeyframeAnimationOptionRepeat animations:^{ UIView *view = self.viewArray[ 5 ]; view.transform = CGAffineTransformMakeScale( 2 , 1 ); //宽高伸缩比例; } completion:^(BOOL finished) { if (finished) { UIView *view = self.viewArray[ 5 ]; view.backgroundColor = [UIColor colorWithRed: arc4random()% 256 / 255.0 green:arc4random()% 256 / 255.0 blue:arc4random()% 256 / 255.0 alpha: 1.0 ]; } }]; [UIView animateKeyframesWithDuration: 5 delay: 0 options:UIViewKeyframeAnimationOptionRepeat animations:^{ UIView *view = self.viewArray[ 6 ]; view.transform = CGAffineTransformMakeTranslation( 300 , 6 ); //xy移动距离; } completion:^(BOOL finished) { if (finished) { UIView *view = self.viewArray[ 6 ]; view.backgroundColor = [UIColor colorWithRed: arc4random()% 256 / 255.0 green:arc4random()% 256 / 255.0 blue:arc4random()% 256 / 255.0 alpha: 1.0 ]; } }]; [UIView animateWithDuration: 0.5 delay: 0 options:UIViewAnimationOptionRepeat animations:^{ UIView *view = self.viewArray[ 7 ]; view.transform = CGAffineTransformMake( 1.5 , 1 , 2 , 2 , 1 , 1 ); //自定义形变,参数自拟; } completion:^(BOOL finished) { if (finished) { UIView *view = self.viewArray[ 7 ]; view.backgroundColor = [UIColor colorWithRed: arc4random()% 256 / 255.0 green:arc4random()% 256 / 255.0 blue:arc4random()% 256 / 255.0 alpha: 1.0 ]; } }]; // 弹簧效果 // 一 动画执行的时间 二 动画延迟执行的时间 第三个 弹簧震动的频率 0 - 1 值越小频率越高 四 弹簧的起始抖动的速度 五 代表动画的效果 六 具体执行的动画 七 执行完之后 的操作 [UIView animateWithDuration: 1 delay: 0 usingSpringWithDamping: 0.1 initialSpringVelocity: 10 options:UIViewAnimationOptionCurveLinear animations:^{ UIView *view = self.viewArray[ 8 ]; if (view.center.x > [UIScreen mainScreen].bounds.size.width) { view.center = CGPointMake( 0 , view.center.y); } else { view.center = CGPointMake(view.center.x + 10 , view.center.y); } } completion:^(BOOL finished) { }]; |
我的理解是UIView的属性动画 就是在一定时间内改变其属性值从而达到动画的效果。
属性动画效果如下,有助于理解不同参数的效果
UIview 属性动画.gif
过渡动画(本来有做gif 图但是不知道为啥放上来不会动了 捂脸!)
图好了
转场.gif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [UIView transitionWithView:self.view3 duration: 1 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{ self.view1.hidden = NO; self.view2.hidden = YES; } completion:^(BOOL finished) { }]; 参数 //转场动画相关的 UIViewAnimationOptionTransitionNone //无转场动画 UIViewAnimationOptionTransitionFlipFromLeft //转场从左翻转 UIViewAnimationOptionTransitionFlipFromRight //转场从右翻转 UIViewAnimationOptionTransitionCurlUp //上卷转场 UIViewAnimationOptionTransitionCurlDown //下卷转场 UIViewAnimationOptionTransitionCrossDissolve //转场交叉消失 UIViewAnimationOptionTransitionFlipFromTop //转场从上翻转 UIViewAnimationOptionTransitionFlipFromBottom //转场从下翻转 |
layer 层动画
layer 层属性 设置一些边框 圆角等
1 2 3 4 5 | view.layer.borderWidth = 6 ; view.layer.borderColor = [UIColor redColor].CGColor; view.layer.cornerRadius = 10 ; CGPoint archP = view.layer.anchorPoint; CGPoint postion = view.layer.position; |
layer 动画 CABasicAnimation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | // 一些常用的key /* transform.scale 比例转化 @(0.8) transform.scale.x 宽的比例 @(0.8) transform.scale.y 高的比例 @(0.8) transform.rotation.x 围绕x轴旋转 @(M_PI) transform.rotation.y 围绕y轴旋转 @(M_PI) transform.rotation.z 围绕z轴旋转 @(M_PI) cornerRadius 圆角的设置 @(50) backgroundColor 背景颜色的变化 (id)[UIColor purpleColor].CGColor bounds 大小,中心不变 [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)]; position 位置(中心点的改变) [NSValue valueWithCGPoint:CGPointMake(300, 300)]; contents 内容,比如UIImageView的图片 imageAnima.toValue = (id)[UIImage imageNamed:@"to"].CGImage; opacity 透明度 @(0.7) contentsRect.size.width 横向拉伸缩放 @(0.4)最好是0~1之间的 */ /* 属性 说明 duration 动画的时长 repeatCount 重复的次数。不停重复设置为 HUGE_VALF repeatDuration 设置动画的时间。在该时间内动画一直执行,不计次数。 beginTime 指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式 timingFunction 设置动画的速度变化 autoreverses 动画结束时是否执行逆动画 fromValue 所改变属性的起始值 toValue 所改变属性的结束时的值 byValue 所改变属性相同起始值的改变量 */ //CABasicAnimation 最终不会修改其属性 只是为了做动画使用 // 设置需要修改的layer层属性 CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@ "position.x" ]; //设置对应的控件Layer层position.x 的起始值 basicAnimation.fromValue = @(- 112 ); // 设置最终值 basicAnimation.toValue = @( 425 ); // 设置时间 basicAnimation.duration = 4 ; // 设置动画重复的次数 basicAnimation.repeatCount = 1000000 ; // 将动画添加到对应视图的layer层上 [view1.layer addAnimation:basicAnimation forKey:nil]; CABasicAnimation *transformAnima = [CABasicAnimation animationWithKeyPath:@ "transform.rotation.y" ]; transformAnima.fromValue = @(M_PI_2); transformAnima.toValue = @(M_PI); transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transformAnima.autoreverses = YES; transformAnima.repeatCount = HUGE_VALF; transformAnima.beginTime = CACurrentMediaTime() + 1 ; // 这两个是在动画结束之后使view 到最终状态而不是原始状态 因为layer 层动画 其实view 本身frame 没有改变的 transformAnima.removedOnCompletion = NO; transformAnima.fillMode = kCAFillModeForwards; // fillMode /* 该属性定义了你的动画在开始和结束时的动作。默认值是 kCAFillModeRemoved。 取值的解释 kCAFillModeRemoved 设置为该值,动画将在设置的 beginTime 开始执行(如没有设置beginTime属性,则动画立即执行),动画执行完成后将会layer的改变恢复原状。 kCAFillModeForwards 设置为该值,动画即使之后layer的状态将保持在动画的最后一帧,而removedOnCompletion的默认属性值是 YES,所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO。 kCAFillModeBackwards 设置为该值,将会立即执行动画的第一帧,不论是否设置了 beginTime属性。观察发现,设置该值,刚开始视图不见,还不知道应用在哪里。 kCAFillModeBoth 该值是 kCAFillModeForwards 和 kCAFillModeBackwards的组合状态 */ // 添加动画 [view.layer addAnimation:transformAnima forKey:@ "A" ]; |
CAKeyframeAnimation 关键帧动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | // 关键帧动画 // 指定动画需要修改的属性 CAKeyframeAnimation *keyFrameA = [CAKeyframeAnimation animationWithKeyPath:@ "position" ]; // 获得起始的点 CGPoint point1 = view12.layer.position; // 第二个点 CGPoint point2 = CGPointMake( 375 / 2.0 , - 50 ); // 第三个点 CGPoint point3 = CGPointMake( 375 + 50 , point1.y); // 第四个点 CGPoint point4 = point1; NSValue *pointV1 = [NSValue valueWithCGPoint:point1]; NSValue *pointV2 = [NSValue valueWithCGPoint:point2]; NSValue *pointV3 = [NSValue valueWithCGPoint:point3]; NSValue *pointV4 = [NSValue valueWithCGPoint:point4]; keyFrameA.values = @[pointV1,pointV2,pointV3,pointV4]; // 设置每帧动画的起始和结束点 keyFrameA.duration = 5 ; // 设置重复的次数 keyFrameA.repeatCount = 1000 ; //将动画添加到指定的控件的layer上; [view12.layer addAnimation:keyFrameA forKey:nil]; //绕矩形循环跑 CALayer * rectLayer = [[CALayer alloc] init]; rectLayer.frame = CGRectMake( 15 , 200 , 30 , 30 ); rectLayer.cornerRadius = 15 ; rectLayer.backgroundColor = [[UIColor blackColor] CGColor]; [self.view.layer addSublayer:rectLayer]; CAKeyframeAnimation *rectRunAnimation = [CAKeyframeAnimation animationWithKeyPath:@ "position" ]; //设定关键帧位置,必须含起始与终止位置 rectRunAnimation.values = @[[NSValue valueWithCGPoint:rectLayer.frame.origin], [NSValue valueWithCGPoint:CGPointMake([UIScreen mainScreen].bounds.size.width - 15 , rectLayer.frame.origin.y)], [NSValue valueWithCGPoint:CGPointMake([UIScreen mainScreen].bounds.size.width - 15 , rectLayer.frame.origin.y + 100 )], [NSValue valueWithCGPoint:CGPointMake( 15 , rectLayer.frame.origin.y + 100 )], [NSValue valueWithCGPoint:rectLayer.frame.origin]]; // CGMutablePathRef path = CGPathCreateMutable() // CGPathMoveToPoint(path, NULL, rectLayer.position.x - 15, rectLayer.position.y - 15); // CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y); // CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y + 100); // CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y + 100); // CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y); // rectRunAnimation.path = path; // CGPathRelease(path); //设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1) rectRunAnimation.keyTimes = @[[NSNumber numberWithFloat: 0.0 ], [NSNumber numberWithFloat: 0.6 ], [NSNumber numberWithFloat: 0.7 ], [NSNumber numberWithFloat: 0.8 ], [NSNumber numberWithFloat: 1 ]]; // 1 kCAMediaTimingFunctionLinear//线性 // 2 kCAMediaTimingFunctionEaseIn//淡入 // 3 kCAMediaTimingFunctionEaseOut//淡出 // 4 kCAMediaTimingFunctionEaseInEaseOut//淡入淡出 // 5 kCAMediaTimingFunctionDefault//默认 rectRunAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]]; rectRunAnimation.repeatCount = 1000 ; rectRunAnimation.autoreverses = NO; // 1 const kCAAnimationLinear//线性,默认 // 2 const kCAAnimationDiscrete//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上 // 3 const kCAAnimationPaced//平均,keyTimes跟timeFunctions失效 // 4 const kCAAnimationCubic//平均,同上 // 5 const kCAAnimationCubicPaced//平均,同上 rectRunAnimation.calculationMode = kCAAnimationLinear; rectRunAnimation.duration = 4 ; rectRunAnimation.removedOnCompletion = NO; rectRunAnimation.fillMode = kCAFillModeForwards; [rectLayer addAnimation:rectRunAnimation forKey:@ "rectRunAnimation" ]; self.rectLayer = rectLayer; } // 抖动示例 // 创建帧动画对象 CAKeyframeAnimation *anim = [CAKeyframeAnimation animation]; // 设置动画属性 anim.keyPath = @ "transform.rotation" ; anim.values = @[@(kAngleToRadian(- 5 )), @(kAngleToRadian( 5 ))]; // 设置动画执行次数 anim.repeatCount = HUGE_VALF; // 设置动画的执行时长 anim.duration = 0.1 ; // 设置动画的自动反转效果 anim.autoreverses = YES; anim.removedOnCompletion = NO; anim.fillMode = kCAFillModeForwards; / 将动画效果添加到lionImage的layer上 [self.imagev.layer addAnimation:anim forKey:nil]; |
本来都有动图的,现在都动不了,大家可以想象下 一个图在左右抖动 , 上面的那个图是 一个小球按着矩形 线路走一会快一会慢 !
图来了
CAKeyframeAnimation.gif
其实关键帧动画相对来说可能会作出比较复杂的效果,使用方法很简单,只是复杂的动画会使用到算法,可能稍微需要思考。
CATransition 转场
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | kCATransitionFade //交叉淡化过渡 kCATransitionMoveIn //移动覆盖原图 kCATransitionPush //新视图将旧视图推出去 kCATransitionReveal //底部显出来 kCATransitionFromRight; kCATransitionFromLeft(默认值) kCATransitionFromTop; kCATransitionFromBottom 注:kCATransitionFade 不支持Subtype CATransition *anima = [CATransition animation]; anima.type = kCATransitionFade; //设置动画的类型 anima.subtype = kCATransitionFromRight; //设置动画的方向 //anima.startProgress = 0.3;//设置动画起点 //anima.endProgress = 0.8;//设置动画终点 anima.duration = 1 .0f; [_demoView.layer addAnimation:anima forKey:@ "fadeAnimation" ]; |
当然很多动画都不是单一的出现的,下面我们就看下动画组合。
其实动画组合无非就是多种动画作用在一个view上面达到的效果
例如
组合动画.gif
动画组合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // 动画组合 CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@ "position.y" ]; positionAnima.duration = 0.8 ; positionAnima.fromValue = @(view.center.y); positionAnima.toValue = @(view.center.y + 100 ); positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; positionAnima.repeatCount = HUGE_VALF; // positionAnima.repeatDuration = 2; positionAnima.removedOnCompletion = NO; positionAnima.fillMode = kCAFillModeForwards; positionAnima.delegate = self; positionAnima.autoreverses = YES; // 执行逆动画 [view.layer addAnimation:positionAnima forKey:@ "AnimationMoveY" ]; /* 放大缩小 */ // 设定为缩放 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@ "transform.scale" ]; // 动画选项设定 animation.duration = 2.5 ; // 动画持续时间 animation.repeatCount = HUGE_VALF; // 重复次数 animation.autoreverses = YES; // 动画结束时执行逆动画 // 缩放倍数 animation.fromValue = [NSNumber numberWithFloat: 1.0 ]; // 开始时的倍率 animation.toValue = [NSNumber numberWithFloat: 2.0 ]; // 结束时的倍率 // 添加动画 animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; [view.layer addAnimation:animation forKey:@ "scale-layer" ]; 效果就是在移动的过程中放大缩小 |
好了,至此都总结完毕,这些都是基础的东西,好好利用这些再复杂的动画也能做出来! 当然,还有粒子效果这里因为没有动图就不先不总结了,好的,谢谢大家的捧场!