之前要作动画方面相关的功能时都是去百度,想着本身也总结下,方便本身记忆和查找,更加深本身对这方面的理解ios
平常开发 UIKIt 层和 Core Animation 层的动画基本能够实现绝大多数需求,而且层级越高 API 的封装程度越高,也越简洁。本文主要讲解 View Animation 和 Core Animation。git
咱们来看看经过 UIView Animation 均可以实现那些动画spring
#pragma mark ---------------------大小动画,frame 改变 - (void)initSizeAnimation { CGRect origin = self.showImage.frame; CGRect terminal = CGRectMake(SCREEN_W/2-100, SCREEN_H/2-100, 200, 200); [UIView animateWithDuration:1 animations:^{ self.showImage.frame = terminal; } completion:^(BOOL finished) { [UIView animateWithDuration:1 animations:^{ self.showImage.frame = origin; }]; }]; }
#pragma mark ------------------拉伸动画 bounds 改变 - (void)initBoundsAnimation { CGRect origin = self.showImage.bounds; //拉伸动画基于view的bound改变,只改变宽高, CGRect terminal = CGRectMake(0, 0, 200, 150); [UIView animateWithDuration:1 animations:^{ self.showImage.bounds = terminal; } completion:^(BOOL finished) { [UIView animateWithDuration:1 animations:^{ self.showImage.bounds = origin; }]; }]; }
#pragma mark ----------------中心位置动画,改变center - (void)initCenterAnimation { CGPoint origin = self.showImage.center; CGPoint terminal = CGPointMake(self.showImage.center.x, self.showImage.center.y-100); [UIView animateWithDuration:1 animations:^{ self.showImage.center = terminal; } completion:^(BOOL finished) { [UIView animateWithDuration:1 animations:^{ self.showImage.center = origin; }]; }]; }
#pragma mark ----------------旋转动画,改变transform - (void)initTransformAnimation { CGAffineTransform origin = self.showImage.transform; [UIView animateWithDuration:2 animations:^{ // self.showImage.transform = CGAffineTransformMakeScale(0.6, 0.6);//缩放 // self.showImage.transform = CGAffineTransformMakeTranslation(60, -60);//偏移 self.showImage.transform = CGAffineTransformMakeRotation(4.0f);//旋转 } completion:^(BOOL finished) { [UIView animateWithDuration:2 animations:^{ self.showImage.transform = origin; }]; }]; }
#pragma mark ----------------透明度动画 改变alpha - (void)initAlphaAnimation { [UIView animateWithDuration:2 animations:^{ self.showImage.alpha = 0.3; } completion:^(BOOL finished) { [UIView animateWithDuration:2 animations:^{ self.showImage.alpha = 1; }]; }]; }
#pragma mark ----------------转场动画 transition - (void)initTransitionAnimation { [UIView transitionWithView:self.showImage duration:2.0 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{ } completion:^(BOOL finished) { [UIView transitionWithView:self.showImage duration:2 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{ } completion:^(BOOL finished) { }]; }]; }
#pragma mark ----------------spring 动画(弹簧效果) - (void)initSpringAnimation { CGRect origin = self.showImage.frame; CGRect terminal = CGRectMake(origin.origin.x+50, origin.origin.y, 150, 150); [UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:4 options:UIViewAnimationOptionCurveLinear animations:^{ self.showImage.frame = terminal; } completion:^(BOOL finished) { [UIView animateWithDuration:1 delay:1 usingSpringWithDamping:0.5 initialSpringVelocity:4 options:UIViewAnimationOptionCurveLinear animations:^{ self.showImage.frame = origin; } completion:^(BOOL finished) { }]; }]; }
#pragma mark ----------------背景颜色动画 改变 background - (void)initBackgroundAnimation { self.showImage.image = [UIImage imageNamed:@"example1"]; [UIView animateKeyframesWithDuration:6.0 delay:0.f options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{ [UIView addKeyframeWithRelativeStartTime:0.f relativeDuration:1.0 / 4 animations:^{ self.showImage.backgroundColor = [UIColor redColor]; }]; [UIView addKeyframeWithRelativeStartTime:1.0 / 4 relativeDuration:1.0 / 4 animations:^{ self.showImage.backgroundColor = [UIColor greenColor]; }]; [UIView addKeyframeWithRelativeStartTime:2.0 / 4 relativeDuration:1.0 / 4 animations:^{ self.showImage.backgroundColor = [UIColor yellowColor]; }]; [UIView addKeyframeWithRelativeStartTime:2.0 / 4 relativeDuration:1.0 / 4 animations:^{ self.showImage.backgroundColor = [UIColor greenColor]; }]; [UIView addKeyframeWithRelativeStartTime:1.0 / 4 relativeDuration:1.0 / 4 animations:^{ self.showImage.backgroundColor = [UIColor whiteColor]; }]; } completion:^(BOOL finished) { NSLog(@"动画结束"); }]; }
UIViewAnimationOptionLayoutSubviews //进行动画时布局子控件 UIViewAnimationOptionAllowUserInteraction //进行动画时容许用户交互 UIViewAnimationOptionBeginFromCurrentState //从当前状态开始动画 UIViewAnimationOptionRepeat //无限重复执行动画 UIViewAnimationOptionAutoreverse //执行动画回路 UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套动画的执行时间设置 UIViewAnimationOptionOverrideInheritedCurve //忽略嵌套动画的曲线设置 UIViewAnimationOptionAllowAnimatedContent //转场:进行动画时重绘视图 UIViewAnimationOptionShowHideTransitionViews //转场:移除(添加和移除图层的)动画效果 UIViewAnimationOptionOverrideInheritedOptions //不继承父动画设置 UIViewAnimationOptionCurveEaseInOut //时间曲线,慢进慢出(默认值) UIViewAnimationOptionCurveEaseIn //时间曲线,慢进 UIViewAnimationOptionCurveEaseOut //时间曲线,慢出 UIViewAnimationOptionCurveLinear //时间曲线,匀速 UIViewAnimationOptionTransitionNone //转场,不使用动画 UIViewAnimationOptionTransitionFlipFromLeft //转场,从左向右旋转翻页 UIViewAnimationOptionTransitionFlipFromRight //转场,从右向左旋转翻页 UIViewAnimationOptionTransitionCurlUp //转场,下往上卷曲翻页 UIViewAnimationOptionTransitionCurlDown //转场,从上往下卷曲翻页 UIViewAnimationOptionTransitionCrossDissolve //转场,交叉消失和出现 UIViewAnimationOptionTransitionFlipFromTop //转场,从上向下旋转翻页 UIViewAnimationOptionTransitionFlipFromBottom //转场,从下向上旋转翻页
UIViewAnimationOptionLayoutSubviews //进行动画时布局子控件 UIViewAnimationOptionAllowUserInteraction //进行动画时容许用户交互 UIViewAnimationOptionBeginFromCurrentState //从当前状态开始动画 UIViewAnimationOptionRepeat //无限重复执行动画 UIViewAnimationOptionAutoreverse //执行动画回路 UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套动画的执行时间设置 UIViewAnimationOptionOverrideInheritedOptions //不继承父动画设置 UIViewKeyframeAnimationOptionCalculationModeLinear //运算模式 :连续 UIViewKeyframeAnimationOptionCalculationModeDiscrete //运算模式 :离散 UIViewKeyframeAnimationOptionCalculationModePaced //运算模式 :均匀执行 UIViewKeyframeAnimationOptionCalculationModeCubic //运算模式 :平滑 UIViewKeyframeAnimationOptionCalculationModeCubicPaced //运算模式 :平滑均匀
Core Animation是直接做用在 CALayer 上的,iOS 和 Mac OS 均可以使用,Core Animation 的动画过程都是在后台操做的,不会阻塞主线程。数组
下面是 Core Animation 所涉及的几个类的继承关系ide
CAMediaTiming 协议中定义了时间、速度、重复次数等,包含属性:布局
CAAnimation 核心动画基础类,不能直接使用动画
timingFunction -> 控制动画的节奏。系统提供的包括:ui
CAPropertyAnimation 属性动画,针对对象的可动画属性进行效果的设置,不可直接使用。url
CABasicAnimation基础动画,经过keyPath对应属性进行控制,须要设置fromValue以及toValue,只能在两个属性间变化。spa
CASpringAnimation 带有初始速度以及阻尼指数等物理参数的属性动画。
CAKeyframeAnimation 关键帧动画,一样经过keyPath对应属性进行控制,但它能够经过values或者path进行多个阶段的控制
CATransition 转场动画,系统提供了不少酷炫效果
CAAnimationGroup 动画组,方便对于多动画的统一控制管理。
在通常的应用开发中,基础动画能够知足大部分的开发需求,主要完成对于对象指定动画属性两个Value之间的动画过渡。
下面展现使用 CABasicAnimation 实现 位移、缩放、透明度、旋转、圆角 的核心代码
switch (button.tag) { case 0: //位移动画 basicAni = [CABasicAnimation animationWithKeyPath:@"position"]; //到达位置 // basicAni.byValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; basicAni.toValue = [NSValue valueWithCGPoint:CGPointMake(_mainLayer.position.x+100, _mainLayer.position.y+100)]; break; case 1: //缩放动画 basicAni = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; //到达缩放 basicAni.toValue = @(0.1f); break; case 2: //透明度动画 basicAni = [CABasicAnimation animationWithKeyPath:@"opacity"]; //透明度 basicAni.toValue=@(0.1f); break; case 3: //旋转动画 basicAni = [CABasicAnimation animationWithKeyPath:@"transform"]; //3D basicAni.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)]; break; case 4: //圆角动画 basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"]; //圆角 basicAni.toValue=@(50); break;
CASpringAnimation 是 iOS9引入的动画类,相似于 UIView 的 spring 动画,可是增长的质量,劲度系数等属相的扩展,继承自 CABaseAnimation,用法也比较简单:
#pragma mark -----------------------CASpringAniamtion - (void)initSpringAnimation { CASpringAnimation *springAni = [CASpringAnimation animationWithKeyPath:@"position"]; springAni.damping = 2; springAni.stiffness = 50; springAni.mass = 1; springAni.initialVelocity = 10; springAni.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 400)]; springAni.duration = springAni.settlingDuration; [_mainLayer addAnimation:springAni forKey:@"springAnimation"]; }
CAKeyframeAnimation和CABasicAnimation同样是CApropertyAnimation的子类,可是CABasicAnimation只能从一个数值(fromValue)变到另外一个数值(toValue)或者添加一个增量数值(byValue),而CAKeyframeAnimation使用values数组能够设置多个关键帧,同时能够利用path能够进行位置或者锚点的动画操做
- (void)initKeyframeAnimation { CAKeyframeAnimation *animation = nil; if (self.animationIndex == 2) {//晃动 animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"]; animation.duration = 0.3; animation.values = @[@(-(4) / 180.0*M_PI),@((4) / 180.0*M_PI),@(-(4) / 180.0*M_PI)]; animation.repeatCount=MAXFLOAT; }else {//曲线位移 animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:_mainLayer.position]; [path addCurveToPoint:CGPointMake(300, 500) controlPoint1:CGPointMake(100, 400) controlPoint2:CGPointMake(300, 450)]; animation.path = path.CGPath; animation.duration = 1; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; } [_mainLayer addAnimation:animation forKey:@"keyFrameAnimation"]; }
转场动画是一种显示样式向另外一种显示样式过渡的效果,系统给出的效果也不少,不过谨慎使用私有API,防止被拒的悲剧.
具体有如下效果:
- (void)initCATransitionAnimation { CATransition *transition = [CATransition animation]; transition.type = @"rippleEffect"; transition.subtype = kCATransitionFromLeft; transition.duration = 1; _mainLayer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"example"].CGImage); [_mainLayer addAnimation:transition forKey:@"transtion"]; }
在咱们实际开发中,咱们可能须要更加复杂的复合运动,那么须要给图层加多个动画,动画组也就应运而生,建立动画组也很简单,首先建立单个动画,而后将建立的多个动画添加到动画组,最后将动画组添加图层上就能够啦。
- (void)initAnimationGroup { //晃动动画 CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"]; keyFrameAni.values = @[@(-(4) / 180.0*M_PI),@((4) / 180.0*M_PI),@(-(4) / 180.0*M_PI)]; //每个动画能够单独设置时间和重复次数,在动画组的时间基础上,控制单动画的效果 keyFrameAni.duration = 0.3; keyFrameAni.repeatCount= MAXFLOAT; keyFrameAni.delegate = self; // keyFrameAni.removedOnCompletion = NO; // keyFrameAni.fillMode = kCAFillModeForwards; //位移动画 CABasicAnimation *basicAni = [CABasicAnimation animationWithKeyPath:@"position"]; //到达位置 basicAni.byValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; // basicAni.duration = 1; basicAni.repeatCount = 1; // basicAni.removedOnCompletion = NO; basicAni.fillMode = kCAFillModeForwards; //设置代理 basicAni.delegate = self; //动画时间 basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; CAAnimationGroup *aniGroup = [CAAnimationGroup animation]; aniGroup.animations = @[keyFrameAni,basicAni]; aniGroup.autoreverses = YES; //动画的表现时间和重复次数由动画组设置的决定 aniGroup.duration = 2; aniGroup.repeatCount= 3; //使动画结束后停留在结束位置 // aniGroup.autoreverses = NO; // aniGroup.removedOnCompletion = NO; // aniGroup.fillMode = kCAFillModeForwards; // [_mainLayer addAnimation:aniGroup forKey:@"groupAnimation"]; }
Core Animation 给咱们展现的只是假象;layer 的 frame、bounds、position 不会在动画完毕后发生改变;
UIView 封装的动画会真实修改 view 的一些属性。
本文总结的内容我的感受仍是比较浅的,但仍是能知足平常开发要求的,固然一些要求比较高的,还须要你们对每一个动画类进行深刻的研究。
最后附上本文的 Demo 地址 : animation