乾貨系列之手把手教你使用Core animation 作動畫

原文出處: Airfei   html

源碼下載:源碼git

最近在技術羣裏,有人發了一張帶有動畫效果的圖片。以爲頗有意思,便動手實現了一下。在這篇文章中你將會學到Core Animation顯式動畫中的關鍵幀動畫、組合動畫、CABasicAnimation動畫。先上一張原圖的動畫效果。github

點擊此查看原圖動畫效果編程

本文要實現的效果圖以下:架構

 

實現的效果圖.gifapp

把原動畫gif動畫在mac上使用圖片瀏覽模式打開,咱們能夠看到動畫每一幀的顯示。從每一幀上的展現過程,能夠把總體的動畫進行拆分紅兩大部分。測試

第一部分(Part1)從初始狀態變成取消狀態(圖片上是由橫實線變成上線橫線交叉的圓)。
第二部分(Part2)從取消狀態變回初始狀態。動畫

下面咱們先詳細分析Part1是怎麼實現的。根據動畫圖,把Part1再細分紅三步。網站

Step1 : 中間橫實線的由右向左的運動效果。這實際上是一個組合動畫。是先向左偏移的同時橫線變短。先看一下實現的動態效果。ui

 

step1 Animation.gif

■ 向左偏移—使用基本動畫中animationWithKeyPath鍵值對的方式來改變更畫的值。咱們這裏使用position.x,一樣能夠使用transform.translation.x來平移。

■ 改變橫線的大小—使用經典的strokeStartstrokeEnd。其實上橫線長度的變化的由strokeStartstrokeEnd之間的值來共同來決定。改變strokeEnd的值由1.0到0.4,不改變strokeStart的值。橫線的長度會從右側方向由1.0倍長度減小到0.4倍長度。參見示意圖的紅色區域。

 

stroke示意圖.png

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

-(void) animationStep1{

 

    //最終changedLayer的狀態

    _changedLayer.strokeEnd = 0.4;

    //基本動畫,長度有1.0減小到0.4

    CABasicAnimation *strokeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];

    strokeAnimation.fromValue = [NSNumber numberWithFloat:1.0f];

    strokeAnimation.toValue = [NSNumber numberWithFloat:0.4f];

    //基本動畫,向左偏移10個像素

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"position.x"];

    pathAnimation.fromValue = [NSNumber numberWithFloat:0.0];

    pathAnimation.toValue = [NSNumber numberWithFloat:-10];

    //組合動畫,平移和長度減小同時進行

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];

    animationGroup.animations = [NSArray arrayWithObjects:strokeAnimation,pathAnimation, nil];

    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

    animationGroup.duration = kStep1Duration;

    //設置代理

    animationGroup.delegate = self;

    animationGroup.removedOnCompletion = YES;

    //監聽動畫

    [animationGroup setValue:@"animationStep1" forKey:@"animationName"];

    //動畫加入到changedLayer上

    [_changedLayer addAnimation:animationGroup forKey:nil];

}

Step2 : 由左向右的動畫–向右偏移同時橫線長度變長。看一下Step2要實現的動畫效果。其思路和Step1是同樣的。

 

step2 Animation.gif

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

-(void)animationStep2

{

    CABasicAnimation *translationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];

    translationAnimation.fromValue = [NSNumber numberWithFloat:-10];

    //strokeEnd:0.8 剩餘的距離toValue = lineWidth * (1 - 0.8);

 

    translationAnimation.toValue = [NSNumber numberWithFloat:0.2 * lineWidth ];

 

    _changedLayer.strokeEnd = 0.8;

    CABasicAnimation *strokeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];

    strokeAnimation.fromValue = [NSNumber numberWithFloat:0.4f];

    strokeAnimation.toValue = [NSNumber numberWithFloat:0.8f];

 

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];

    animationGroup.animations = [NSArray arrayWithObjects:strokeAnimation,translationAnimation, nil];

    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    animationGroup.duration = kStep2Duration;

    //設置代理

    animationGroup.delegate = self;

    animationGroup.removedOnCompletion = YES;

    [animationGroup setValue:@"animationStep2" forKey:@"animationName"];

    [_changedLayer addAnimation:animationGroup forKey:nil];

}

Step3: 圓弧的動畫效果和上下兩個橫實線的動畫效果。

  1. 畫圓弧,首先想到是使用UIBezierPath。畫個示意圖來分析動畫路徑。示意圖以下:

 

step3 示意圖.jpg

整個path路徑是由三部分組成,ABC曲線CD圓弧DD′圓
使用UIBezierPath的方法

1

- (void)appendPath:(UIBezierPath *)bezierPath;

把三部分路徑關聯起來。詳細講解思路。

• ABC曲線就是貝塞爾曲線,能夠根據A、B、C三點的位置使用方法

1

2

3

4

5

//endPoint 終點座標 controlPoint1 起點座標

//controlPoint2 起點和終點在曲線上的切點延伸相交的交點座標

- (void)addCurveToPoint:(CGPoint)endPoint

          controlPoint1:(CGPoint)controlPoint1

          controlPoint2:(CGPoint)controlPoint2;

二次貝塞爾曲線示意圖以下:

 

二次貝塞爾曲線.png

其中control point 點是從曲線上取 start point和end point 切點相交匯的所獲得的交點。以下圖:

 

control point .png

首先C點取圓上的一點,-30°。那麼,

1

CGFloat angle = Radians(30);

C點座標爲:

1

2

3

    //C點

    CGFloat endPointX = self.center.x + Raduis * cos(angle);

    CGFloat endPointY = kCenterY - Raduis * sin(angle);

A點座標爲:

1

2

3

    //A點 取橫線最右邊的點

    CGFloat startPointX = self.center.x + lineWidth/2.0 ;

    CGFloat startPointY = controlPointY;

control point 爲E點:

1

2

3

    //E點 半徑*反餘弦(30°)

    CGFloat startPointX = self.center.x + Raduis *acos(angle);

    CGFloat startPointY = controlPointY;

• CD圓弧的路徑使用此方法肯定

1

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

關於弧度問題,UIBezierPath的官方文檔中的這張圖:

 

弧度.jpg

StartAngle 弧度即C點弧度,EndAngel弧度即D點弧度。

1

2

CGFloat StartAngle = 2 * M_PI - angle;

CGFloat EndAngle = M_PI + angle;

• DD′圓的路徑和上面2同樣的方法肯定。

StartAngle 弧度即D點弧度,EndAngel弧度即D′點弧度。

1

2

CGFloat StartAngle = M_PI *3/2 - (M_PI_2 -angle);

CGFloat EndAngle = -M_PI_2 - (M_PI_2 -angle);

下面部分代碼是全部path路徑。

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

    UIBezierPath *path = [UIBezierPath bezierPath];

 

    // 畫貝塞爾曲線 圓弧

    [path moveToPoint:CGPointMake(self.center.x +  lineWidth/2.0 , kCenterY)];

 

     CGFloat angle = Radians(30);

    //C點

    CGFloat endPointX = self.center.x + Raduis * cos(angle);

    CGFloat endPointY = kCenterY - Raduis * sin(angle);

    //A點

    CGFloat startPointX = self.center.x + lineWidth/2.0;

    CGFloat startPointY = kCenterY;

    //E點 半徑*反餘弦(30°)

    CGFloat controlPointX = self.center.x + Raduis *acos(angle);

    CGFloat controlPointY = kCenterY;

 

    //貝塞爾曲線 ABC曲線

    [path addCurveToPoint:CGPointMake(endPointX, endPointY)

            controlPoint1:CGPointMake(startPointX , startPointY)

            controlPoint2:CGPointMake(controlPointX , controlPointY)];

 

    // (360°- 30°) ->(180°+30°) 逆時針的圓弧 CD圓弧

    UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.center.x,kCenterY)

                                                         radius:Raduis

                                                     startAngle:2 * M_PI - angle

                                                       endAngle:M_PI + angle

                                                      clockwise:NO];

    [path appendPath:path1];

     // (3/2π- 60°) ->(-1/2π -60°) 逆時針的圓 DD′圓

    UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.center.x,kCenterY)

                                                        radius:Raduis

                                                    startAngle:M_PI *3/2 - (M_PI_2 -angle)

                                                      endAngle:-M_PI_2 - (M_PI_2 -angle)

                                                     clockwise:NO];

 

    [path appendPath:path2];

 

    _changedLayer.path = path.CGPath;

Path路徑有了,接着實現動畫效果。
圓弧的長度逐漸變長。咱們仍是使用經典的strokeStartstrokeEnd。可是圓弧是如何變長的呢?

(1) 初始圓弧有一段長度。
(2) 在原始長度的基礎上逐漸變長,逐漸遠離A點,同時要在D點中止。
(3) 長度逐漸變長,最終要在D與D′點交匯。

咱們分別解決這個三個問題。

第一個問題,strokeEnd - strokeStart > 0這樣能保證有一段圓弧。

第二個問題,逐漸變長,意味着strokeEnd值不斷變大。遠離A點意味着strokeStart的值不斷變大。在D點中止,說明了strokeStart有上限值。

第三個問題,意味着strokeEnd值不斷變大,最終值爲1.0。

這三個問題說明了一個問題,strokeEndstrokeStart是一組變化的數據。

那麼core animation 中能夠控制一組值的動畫是關鍵幀動畫(CAKeyframeAnimation)。

爲了更準確的給出strokeEndstrokeStart值,咱們使用長度比來肯定。

假設咱們初始的長度就是曲線ABC的長度。可是貝塞爾曲線長度怎麼計算?使用下面方法:

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

//求貝塞爾曲線長度

-(CGFloat) bezierCurveLengthFromStartPoint:(CGPoint)start toEndPoint:(CGPoint) end withControlPoint:(CGPoint) control

{

    const int kSubdivisions = 50;

    const float step = 1.0f/(float)kSubdivisions;

 

    float totalLength = 0.0f;

    CGPoint prevPoint = start;

 

    // starting from i = 1, since for i = 0 calulated point is equal to start point

    for (int i = 1; i <= kSubdivisions; i++)

    {

        float t = i*step;

 

        float x = (1.0 - t)*(1.0 - t)*start.x + 2.0*(1.0 - t)*t*control.x + t*t*end.x;

        float y = (1.0 - t)*(1.0 - t)*start.y + 2.0*(1.0 - t)*t*control.y + t*t*end.y;

 

        CGPoint diff = CGPointMake(x - prevPoint.x, y - prevPoint.y);

 

        totalLength += sqrtf(diff.x*diff.x + diff.y*diff.y); // Pythagorean

 

        prevPoint = CGPointMake(x, y);

    }

 

    return totalLength;

}

計算貝塞爾曲線所在的比例爲:

1

CGFloat orignPercent = [self calculateCurveLength]/[self calculateTotalLength];

初始的strokeStart = 0strokeEnd = orignPercent
最終的stokeStart = ?

1

2

//結果就是貝塞爾曲線長度加上120°圓弧的長度與總長度相比獲得的結果。

CGFloat endPercent =([self calculateCurveLength] + Radians(120) *Raduis ) / [self calculateTotalLength];

實現動畫的代碼爲

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

    CGFloat orignPercent = [self calculateCurveLength] / [self calculateTotalLength];

    CGFloat endPercent =([self calculateCurveLength] + Radians(120) *Raduis ) / [self calculateTotalLength];

 

    _changedLayer.strokeStart = endPercent;

 

    //方案1

    CAKeyframeAnimation *startAnimation = [CAKeyframeAnimation animationWithKeyPath:@"strokeStart"];

    startAnimation.values = @[@0.0,@(endPercent)];

 

    CAKeyframeAnimation *EndAnimation = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];

    EndAnimation.values = @[@(orignPercent),@1.0];

 

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];

    animationGroup.animations = [NSArray arrayWithObjects:startAnimation,EndAnimation, nil];

    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    animationGroup.duration = kStep3Duration;

    animationGroup.delegate = self;

    animationGroup.removedOnCompletion = YES;

    [animationGroup setValue:@"animationStep3" forKey:@"animationName"];

    [_changedLayer addAnimation:animationGroup forKey:nil];

效果圖爲:

 

step3-1 Animation.gif

2.上下橫線的動畫效果。

此動畫效果,須要使用transform.rotation.z轉動角度。

上橫線轉動的角度順序爲 0 -> 10° -> (-55°) -> (-45°)
這是一組數據,使用關鍵幀處理動畫。

1

2

3

4

5

6

    CAKeyframeAnimation *rotationAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation1.values = @[[NSNumber numberWithFloat:0],

                                 [NSNumber numberWithFloat:Radians(10) ],

                                 [NSNumber numberWithFloat:Radians(-10) - M_PI_4 ],

                                 [NSNumber numberWithFloat:- M_PI_4 ]

                                 ];

下橫線轉動的角度順序爲0 -> (-10°) -> (55°) -> (45°)

1

2

3

4

5

6

    CAKeyframeAnimation *rotationAnimation2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation2.values = @[[NSNumber numberWithFloat:0],

                                 [NSNumber numberWithFloat:Radians(-10) ],

                                 [NSNumber numberWithFloat:Radians(10)  + M_PI_4 ],

                                 [NSNumber numberWithFloat: M_PI_4 ]

                                 ];

你認爲這麼就結束了? 最終結束的動畫以下:

 

step3-2 finished Animation.jpg

發現相交的直線沒有居中,而是靠左顯示。

向左平移,使用transform.translation.x

1

2

    //平移量

    CGFloat toValue = lineWidth *(1- cos(M_PI_4)) /2.0;

即旋轉角度又發生偏移量,使用組合動畫。

上橫線組合動畫

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

     //平移x

    CABasicAnimation *translationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];

    translationAnimation.fromValue = [NSNumber numberWithFloat:0];

    translationAnimation.toValue = [NSNumber numberWithFloat:-toValue];

 

    //角度關鍵幀 上橫線的關鍵幀 0 - 10° - (-55°) - (-45°)

    CAKeyframeAnimation *rotationAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation1.values = @[[NSNumber numberWithFloat:0],

                                 [NSNumber numberWithFloat:Radians(10) ],

                                 [NSNumber numberWithFloat:Radians(-10) - M_PI_4 ],

                                 [NSNumber numberWithFloat:- M_PI_4 ]

                                 ];

 

    CAAnimationGroup *transformGroup1 = [CAAnimationGroup animation];

    transformGroup1.animations = [NSArray arrayWithObjects:rotationAnimation1,translationAnimation, nil];

    transformGroup1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    transformGroup1.duration = kStep3Duration;

    transformGroup1.removedOnCompletion = YES;

    [_topLineLayer addAnimation:transformGroup1 forKey:nil];

下橫線組合動畫

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

    //角度關鍵幀 下橫線的關鍵幀 0 - (-10°) - (55°) - (45°)

    CAKeyframeAnimation *rotationAnimation2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation2.values = @[[NSNumber numberWithFloat:0],

                                 [NSNumber numberWithFloat:Radians(-10) ],

                                 [NSNumber numberWithFloat:Radians(10) + M_PI_4 ],

                                 [NSNumber numberWithFloat: M_PI_4 ]

                                 ];

 

    CAAnimationGroup *transformGroup2 = [CAAnimationGroup animation];

    transformGroup2.animations = [NSArray arrayWithObjects:rotationAnimation2,translationAnimation, nil];

    transformGroup2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    transformGroup2.duration = kStep3Duration ;

    transformGroup2.delegate = self;

    transformGroup2.removedOnCompletion = YES;

    [_bottomLineLayer addAnimation:transformGroup2 forKey:nil];

Part1到此結束。最終效果圖

 

Part1 animation.gif

Part2的思路和Part1思路是同樣的。你能夠參考代碼本身思考一下。核心代碼

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

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

-(void)cancelAnimation

{

    //最關鍵是path路徑

 

    UIBezierPath *path = [UIBezierPath bezierPath];

    //30度,通過反覆測試,效果最好

    CGFloat angle = Radians(30);

 

    CGFloat startPointX = self.center.x + Raduis * cos(angle);

    CGFloat startPointY = kCenterY - Raduis * sin(angle);

 

    CGFloat controlPointX = self.center.x + Raduis *acos(angle);

    CGFloat controlPointY = kCenterY;

 

    CGFloat endPointX = self.center.x + lineWidth /2;

    CGFloat endPointY = kCenterY;

 

    //組合path 路徑 起點 -150° 順時針的圓

    path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.center.x,kCenterY)

                                                         radius:Raduis

                                                     startAngle:-M_PI + angle

                                                       endAngle:M_PI + angle

                                                      clockwise:YES];

 

    //起點爲 180°-> (360°-30°)

    UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.center.x,kCenterY)

                                                         radius:Raduis

                                                     startAngle:M_PI + angle

                                                       endAngle:2 * M_PI - angle

                                                      clockwise:YES];

    [path appendPath:path1];

 

    //三點曲線

    UIBezierPath *path2 = [UIBezierPath bezierPath];

 

    [path2 moveToPoint:CGPointMake(startPointX, startPointY)];

 

    [path2 addCurveToPoint:CGPointMake(endPointX,endPointY)

             controlPoint1:CGPointMake(startPointX, startPointY)

             controlPoint2:CGPointMake(controlPointX, controlPointY)];

 

    [path appendPath:path2];

 

    //比原始狀態向左偏移5個像素

    UIBezierPath *path3 = [UIBezierPath bezierPath];

    [path3 moveToPoint:CGPointMake(endPointX,endPointY)];

    [path3 addLineToPoint:CGPointMake(self.center.x - lineWidth/2 -5,endPointY)];

    [path appendPath:path3];

 

    _changedLayer.path = path.CGPath;

 

    //平移量

    CGFloat toValue = lineWidth *(1- cos(M_PI_4)) /2.0;

    //finished 最終狀態

    CGAffineTransform transform1 = CGAffineTransformMakeRotation(0);

    CGAffineTransform transform2 = CGAffineTransformMakeTranslation(0, 0);

    CGAffineTransform transform3 = CGAffineTransformMakeRotation(0);

 

    CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);

    _topLineLayer.affineTransform = transform;

    transform = CGAffineTransformConcat(transform3, transform2);

    _bottomLineLayer.affineTransform = transform;

 

    //一個圓的長度比

    CGFloat endPercent = 2* M_PI *Raduis / ([self calculateTotalLength] + lineWidth);

 

    //橫線佔總path的百分比

    CGFloat percent = lineWidth / ([self calculateTotalLength] + lineWidth);

 

    _changedLayer.strokeStart = 1.0 -percent;

 

    CAKeyframeAnimation *startAnimation = [CAKeyframeAnimation animationWithKeyPath:@"strokeStart"];

    startAnimation.values = @[@0.0,@0.3,@(1.0 -percent)];

 

    //在π+ angle

    CAKeyframeAnimation *EndAnimation = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];

    EndAnimation.values = @[@(endPercent),@(endPercent),@1.0];

 

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];

    animationGroup.animations = [NSArray arrayWithObjects:startAnimation,EndAnimation, nil];

    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    animationGroup.duration = kStep4Duration;

    animationGroup.delegate = self;

    animationGroup.removedOnCompletion = YES;

    [animationGroup setValue:@"animationStep4" forKey:@"animationName"];

    [_changedLayer addAnimation:animationGroup forKey:nil];

 

    //平移x

    CABasicAnimation *translationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];

    translationAnimation.fromValue = [NSNumber numberWithFloat:-toValue];

    translationAnimation.toValue = [NSNumber numberWithFloat:0];

 

    //角度關鍵幀 上橫線的關鍵幀  (-45°) -> (-55°)-> 10° -> 0

    CAKeyframeAnimation *rotationAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation1.values = @[[NSNumber numberWithFloat:- M_PI_4 ],

                                  [NSNumber numberWithFloat:- Radians(10) - M_PI_4 ],

                                  [NSNumber numberWithFloat:Radians(10) ],

                                  [NSNumber numberWithFloat:0]

                                  ];

 

    CAAnimationGroup *transformGroup1 = [CAAnimationGroup animation];

    transformGroup1.animations = [NSArray arrayWithObjects:rotationAnimation1,translationAnimation, nil];

    transformGroup1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    transformGroup1.duration = kStep4Duration;

    transformGroup1.removedOnCompletion = YES;

    [_topLineLayer addAnimation:transformGroup1 forKey:nil];

 

    //角度關鍵幀 下橫線的關鍵幀  (45°)-> (55°)- >(-10°)-> 0

    CAKeyframeAnimation *rotationAnimation2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation2.values = @[[NSNumber numberWithFloat: M_PI_4 ],

                                  [NSNumber numberWithFloat:Radians(10) + M_PI_4 ],

                                  [NSNumber numberWithFloat:-Radians(10) ],

                                  [NSNumber numberWithFloat:0]

                                  ];

 

    CAAnimationGroup *transformGroup2 = [CAAnimationGroup animation];

    transformGroup2.animations = [NSArray arrayWithObjects:rotationAnimation2,translationAnimation, nil];

    transformGroup2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    transformGroup2.duration = kStep4Duration;

    transformGroup2.delegate = self;

    transformGroup2.removedOnCompletion = YES;

    [_bottomLineLayer addAnimation:transformGroup2 forKey:nil];

 

}

最終效果圖:

 

finished animation.gif

本篇文章講解結束!

代碼點此連接下載:https://github.com/WZF-Fei/ZFChangeAnimation

http://cxy.liuzhihengseo.com/465.html

問啊-定製化IT教育平臺,牛人一對一服務,有問必答,開發編程社交頭條 官方網站:www.wenaaa.com 下載問啊APP,參與官方懸賞,賺百元現金。QQ羣290551701 彙集不少互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!

相關文章
相關標籤/搜索