之前要作動畫方面相關的功能時都是去百度,想着本身也總結下,方便本身記憶和查找,更加深本身對這方面的理解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