首先讓我們了解下什么是 Core Animation,Core Animation 為核心動畫,他為圖形渲染和動畫提供了基礎。使用核心動畫,我們只需要設置起點、終點、關鍵幀等一些參數,剩下的工作核心動畫會自動幫我們處理。(學過 Flash 的朋友會有種似曾相識的感覺)
核心動畫開發動畫的本質是將 CALayer 中的內容轉換為位圖從而供硬件操作,他不用消耗 CPU 資源,合理使用他能提高 App 性能。
核心動畫的幾大核心類:
CAAnimation「核心動畫基類」:不能直接使用,他遵循並實現了 CAMediaTiming 協議,負責動畫運行時間和速度的控制。
CAPropertyAnimation「屬性動畫基類」:不能直接使用,他通過可動畫屬性進行動畫設置。
CAAnimationGroup「動畫組」:他是一種組合模式,可以組合多個動畫進行動畫行為的統一控制。
CATransition「轉場動畫」:主要通過濾鏡進行動畫效果設置。
CABasicAnimation「基礎動畫」:通過起點和終點狀態屬性參數進行動畫控制。
CAKeyframeAnimation「關鍵幀動畫」:同 CABasicAnimation 一樣通過屬性參數進行動畫控制,但不同的是他可以有多個狀態控制,不單單只有起點和終點。
CABasicAnimation 和 CAKeyframeAnimation 都屬於 CAPropertyAnimation,他們通過修改屬性參數產生動畫效果。在兩個狀態點中間過程的動畫,可以稱為「補間動畫」,他由系統自動計算產生。CABasicAnimation 只有起點和終點狀態,從某種角度來說,他相當於有兩個關鍵幀的 CAKeyframeAnimation。
下面讓我們通過例子,了解如何使用 CAKeyframeAnimation「關鍵幀動畫」、CABasicAnimation「基礎動畫」、CAAnimationGroup「動畫組」吧。
效果如下:
ViewController.h
1 #import <UIKit/UIKit.h> 2 3 @interface ViewController : UIViewController 4 @property (strong, nonatomic) IBOutlet UIImageView *imgVAnimation; 5 @property (strong, nonatomic) IBOutlet UIButton *btnAnimation1; 6 @property (strong, nonatomic) IBOutlet UIButton *btnAnimation2; 7 8 @end
ViewController.m
1 #import "ViewController.h" 2 3 @interface ViewController () 4 - (void)modifyLayerForButton:(UIButton *)btn; 5 - (void)layoutUI; 6 @end 7 8 @implementation ViewController 9 #define kCornerRadiusOfImage CGRectGetWidth(_imgVAnimation.frame)/2.0 10 11 - (void)viewDidLoad { 12 [super viewDidLoad]; 13 14 [self layoutUI]; 15 } 16 17 - (void)didReceiveMemoryWarning { 18 [super didReceiveMemoryWarning]; 19 // Dispose of any resources that can be recreated. 20 } 21 22 - (void)modifyLayerForButton:(UIButton *)btn { 23 btn.layer.masksToBounds = YES; 24 btn.layer.cornerRadius = 5.0; 25 btn.layer.borderColor = [UIColor grayColor].CGColor; 26 btn.layer.borderWidth = 1.0; 27 } 28 29 - (void)layoutUI { 30 //圖片視圖 31 _imgVAnimation.layer.masksToBounds = YES; 32 _imgVAnimation.layer.cornerRadius = kCornerRadiusOfImage; 33 _imgVAnimation.layer.borderColor = [UIColor orangeColor].CGColor; 34 _imgVAnimation.layer.borderWidth = 2.0; 35 36 //按鈕 37 [self modifyLayerForButton:_btnAnimation1]; 38 [self modifyLayerForButton:_btnAnimation2]; 39 } 40 41 - (IBAction)btnAnimation1DidPush:(id)sender { 42 //移到右下角;使用關鍵幀動畫,移動路徑為預定的貝塞爾曲線路徑 43 CGPoint fromPoint = _imgVAnimation.center; 44 CGFloat toPointX = self.view.frame.size.width - kCornerRadiusOfImage; 45 CGFloat toPointY = self.view.frame.size.height - kCornerRadiusOfImage; 46 CGPoint toPoint = CGPointMake(toPointX, toPointY); 47 CGPoint controlPoint = CGPointMake(toPointX, 0.0); 48 49 UIBezierPath *path = [UIBezierPath bezierPath]; 50 [path moveToPoint:fromPoint]; 51 [path addQuadCurveToPoint:toPoint controlPoint:controlPoint]; 52 53 CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 54 positionAnimation.path = path.CGPath; 55 positionAnimation.removedOnCompletion = YES; 56 57 //變小;使用基礎動畫 58 CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 59 transformAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity]; 60 transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)]; //設置 X 軸和 Y 軸縮放比例都為1.0,而 Z 軸不變 61 transformAnimation.removedOnCompletion = YES; 62 63 //透明;使用基礎動畫 64 CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 65 opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0]; 66 opacityAnimation.toValue = [NSNumber numberWithFloat:0.1]; 67 opacityAnimation.removedOnCompletion = YES; 68 69 //組合效果;使用動畫組 70 CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 71 animationGroup.animations = @[ positionAnimation, transformAnimation, opacityAnimation ]; 72 animationGroup.duration = 1.0; //設置動畫執行時間;這里設置為1.0秒 73 animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; //設置媒體調速運動;默認為 kCAMediaTimingFunctionLinear,即為線型間隔;這里設置為 kCAMediaTimingFunctionEaseIn,即先慢后快,相當於有個加速度 74 animationGroup.autoreverses = YES; //設置自動倒退,即動畫回放;默認值為NO 75 [_imgVAnimation.layer addAnimation:animationGroup forKey:nil]; 76 } 77 78 - (IBAction)btnAnimation2DidPush:(id)sender { 79 //向右移動;使用關鍵幀動畫,移動路徑為預定的直線路徑 80 CGPoint fromPoint = _imgVAnimation.center; 81 CGPoint toPoint = CGPointMake(fromPoint.x + 100.0, fromPoint.y); 82 83 UIBezierPath *path = [UIBezierPath bezierPath]; 84 [path moveToPoint:fromPoint]; 85 [path addLineToPoint:toPoint]; 86 87 CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 88 positionAnimation.path = path.CGPath; 89 positionAnimation.removedOnCompletion = YES; 90 91 //旋轉;使用基礎動畫 92 CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 93 transformAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity]; 94 transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0.0, 0.0, 1.0)]; //設置沿着 Z 軸順時針旋轉90度;注意 CATransform3DMakeRotation 總是按最短路徑來選擇,當順時針和逆時針的路徑相同時(e.g. M_PI),會使用逆時針 95 transformAnimation.repeatCount = 8.0; //設置動畫播放重復次數;這里設置為8.0次,共720度 96 transformAnimation.duration = 0.5; //設置動畫執行時間;這里設置為0.5秒 97 transformAnimation.cumulative = YES; //設置是否累積;默認值為NO,這里設置為YES,看起來才動畫效果連貫 98 transformAnimation.removedOnCompletion = YES; 99 100 //組合效果;使用動畫組 101 CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 102 animationGroup.animations = @[ positionAnimation, transformAnimation ]; 103 animationGroup.duration = 4.0; //設置動畫執行時間;這里設置為4.0秒 104 animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; //設置媒體調速運動;默認為 kCAMediaTimingFunctionLinear,即為線型間隔;這里設置為 kCAMediaTimingFunctionEaseIn,即先慢后快,相當於有個加速度 105 animationGroup.autoreverses = YES; //設置自動倒退,即動畫回放;默認值為NO 106 107 //以下兩句是『動畫結束后回到初始狀態的現象』的解決方法;這里沒用到 108 //animationGroup.removedOnCompletion = NO; //設置是否完成后從對應的所屬圖層移除他,默認為YES 109 //animationGroup.fillMode = kCAFillModeForwards; //設置動畫填充模式;默認值為 kCAFillModeRemoved,即動畫執行完就移除,變回原來的狀態,這里設置為 kCAFillModeForwards,即保持向前的狀態 110 [_imgVAnimation.layer addAnimation:animationGroup forKey:nil]; 111 } 112 113 @end
Main.storyboard
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="vXZ-lx-hvc"> 3 <dependencies> 4 <deployment identifier="iOS"/> 5 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/> 6 </dependencies> 7 <scenes> 8 <!--View Controller--> 9 <scene sceneID="ufC-wZ-h7g"> 10 <objects> 11 <viewController id="vXZ-lx-hvc" customClass="ViewController" sceneMemberID="viewController"> 12 <layoutGuides> 13 <viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/> 14 <viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/> 15 </layoutGuides> 16 <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS"> 17 <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> 18 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> 19 <subviews> 20 <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Emoticon_tusiji_icon2" translatesAutoresizingMaskIntoConstraints="NO" id="j2r-O5-Hj2"> 21 <rect key="frame" x="20" y="40" width="150" height="150"/> 22 </imageView> 23 <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aiO-kP-xCF"> 24 <rect key="frame" x="20" y="243" width="150" height="50"/> 25 <state key="normal" title="移到右下角變小透明"> 26 <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/> 27 </state> 28 <connections> 29 <action selector="btnAnimation1DidPush:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="7Z2-yc-1vS"/> 30 </connections> 31 </button> 32 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="圖片操作:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YH5-Oi-KEH"> 33 <rect key="frame" x="20" y="208" width="150" height="21"/> 34 <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> 35 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> 36 <nil key="highlightedColor"/> 37 </label> 38 <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hSL-o5-Ism"> 39 <rect key="frame" x="20" y="311" width="150" height="50"/> 40 <state key="normal" title="旋轉並向右移動"> 41 <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/> 42 </state> 43 <connections> 44 <action selector="btnAnimation2DidPush:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="lC4-zx-uIb"/> 45 </connections> 46 </button> 47 </subviews> 48 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> 49 </view> 50 <connections> 51 <outlet property="btnAnimation1" destination="aiO-kP-xCF" id="kSp-82-S2R"/> 52 <outlet property="btnAnimation2" destination="hSL-o5-Ism" id="6Mz-Wd-xfN"/> 53 <outlet property="imgVAnimation" destination="j2r-O5-Hj2" id="Gmp-iW-kaX"/> 54 </connections> 55 </viewController> 56 <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/> 57 </objects> 58 </scene> 59 </scenes> 60 <resources> 61 <image name="Emoticon_tusiji_icon2" width="150" height="150"/> 62 </resources> 63 </document>