iOS核心動畫詳解(CABasicAnimation)


前言

  上一篇已經介紹了核心動畫在UI渲染中的位置和基本概念,但是沒有具體介紹CAAnimation子類的用法,本文將介紹CABasicAnimation及其子類CASpringAnimation的用法和一些注意事項。

一、CABasicAnimation

1.什么是CABasicAnimation

  CABasicAnimation是核心動畫類簇中的一個類,其父類是CAPropertyAnimation,其子類是CASpringAnimation,它的祖父是CAAnimation。它主要用於制作比較單一的動畫,例如,平移、縮放、旋轉、顏色漸變、邊框的值的變化等,也就是將layer的某個屬性值從一個值到另一個值的變化。類似x -> y這種變化,然而對於x -> y -> z甚至更多的變化是不行的。

2.常用屬性

  @property(nullable, strong) id fromValue;

  @property(nullable, strong) id toValue;

  @property(nullable, strong) id byValue;

  很明顯,fromvalue表示初始狀態,tovalue表示最終狀態,byvalue是在fromvalue的基礎上發生的變化,這個可以慢慢測試,主要還是from和to。

3.實例化方法

  + (instancetype)animationWithKeyPath:(nullable NSString *)path;

  下面是對keypath比較全面的總結,每個keypath對應一種屬性值的變化,其中涉及到顏色變化的都必須使用CGColor,因為對應是對layer的屬性。

 1 #ifndef AnimationKeyPathName_h
 2 #define AnimationKeyPathName_h
 3 #import <Foundation/Foundation.h>
 4 /* CATransform3D Key Paths */
 5 /* 旋轉x,y,z分別是繞x,y,z軸旋轉 */
 6 static NSString *kCARotation = @"transform.rotation";
 7 static NSString *kCARotationX = @"transform.rotation.x";
 8 static NSString *kCARotationY = @"transform.rotation.y";
 9 static NSString *kCARotationZ = @"transform.rotation.z";
10 
11 /* 縮放x,y,z分別是對x,y,z方向進行縮放 */
12 static NSString *kCAScale = @"transform.scale";
13 static NSString *kCAScaleX = @"transform.scale.x";
14 static NSString *kCAScaleY = @"transform.scale.y";
15 static NSString *kCAScaleZ = @"transform.scale.z";
16 
17 /* 平移x,y,z同上 */
18 static NSString *kCATranslation = @"transform.translation";
19 static NSString *kCATranslationX = @"transform.translation.x";
20 static NSString *kCATranslationY = @"transform.translation.y";
21 static NSString *kCATranslationZ = @"transform.translation.z";
22 
23 /* 平面 */
24 /* CGPoint中心點改變位置,針對平面 */
25 static NSString *kCAPosition = @"position";
26 static NSString *kCAPositionX = @"position.x";
27 static NSString *kCAPositionY = @"position.y";
28 
29 /* CGRect */
30 static NSString *kCABoundsSize = @"bounds.size";
31 static NSString *kCABoundsSizeW = @"bounds.size.width";
32 static NSString *kCABoundsSizeH = @"bounds.size.height";
33 static NSString *kCABoundsOriginX = @"bounds.origin.x";
34 static NSString *kCABoundsOriginY = @"bounds.origin.y";
35 
36 /* 透明度 */
37 static NSString *kCAOpacity = @"opacity";
38 /* 背景色 */
39 static NSString *kCABackgroundColor = @"backgroundColor";
40 /* 圓角 */
41 static NSString *kCACornerRadius = @"cornerRadius";
42 /* 邊框 */
43 static NSString *kCABorderWidth = @"borderWidth";
44 /* 陰影顏色 */
45 static NSString *kCAShadowColor = @"shadowColor";
46 /* 偏移量CGSize */
47 static NSString *kCAShadowOffset = @"shadowOffset";
48 /* 陰影透明度 */
49 static NSString *kCAShadowOpacity = @"shadowOpacity";
50 /* 陰影圓角 */
51 static NSString *kCAShadowRadius = @"shadowRadius";
52 #endif /* AnimationKeyPathName_h */

4.簡單用法

  下面的類是用來測試不同keypath對應的動畫,有些省略了,因為原理都是一樣的。

 
         

  #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width

  #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height

  1 #import "BaseAnimationView.h"
  2 
  3 @interface BaseAnimationView()<UITableViewDelegate,UITableViewDataSource>
  4 @property (nonatomic, strong) UIView *squareView;
  5 @property (nonatomic, strong) UILabel *squareLabel;
  6 @property (nonatomic, strong) UITableView *tableView;
  7 @property (nonatomic, strong) NSMutableArray *dataSource;
  8 @end
  9 
 10 @implementation BaseAnimationView
 11 
 12 - (instancetype)init{
 13     if (self = [super initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]) {
 14         [self initData];
 15         [self setupUI];
 16     }
 17     return self;
 18 }
 19 - (void)setupUI{
 20     self.squareView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
 21     self.squareView.backgroundColor = [UIColor cyanColor];
 22     self.squareView.layer.borderColor = [UIColor redColor].CGColor;
 23     self.squareView.center = CGPointMake(SCREEN_WIDTH/2.0, 200);
 24     self.squareView.layer.shadowOpacity = 0.6;
 25     self.squareView.layer.shadowOffset = CGSizeMake(0, 0);
 26     self.squareView.layer.shadowRadius = 4;
 27     self.squareView.layer.shadowColor = [UIColor redColor].CGColor;
 28     [self addSubview:self.squareView];
 29     
 30     self.squareLabel = [[UILabel alloc] initWithFrame:self.squareView.bounds];
 31     self.squareLabel.text = @"label";
 32     self.squareLabel.textAlignment = NSTextAlignmentCenter;
 33     self.squareLabel.textColor = [UIColor blackColor];
 34     self.squareLabel.font = [UIFont systemFontOfSize:17];
 35     [self.squareView addSubview:self.squareLabel];
 36     
 37     self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 400, SCREEN_WIDTH, SCREEN_HEIGHT-400) style:UITableViewStylePlain];
 38     self.tableView.delegate = self;
 39     self.tableView.dataSource = self;
 40     [self addSubview:self.tableView];
 41 }
 42 
 43 - (CABasicAnimation *)getAnimationKeyPath:(NSString *)keyPath fromValue:(id)fromValue toValue:(id)toValue{
 44     CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:keyPath];
 45     basicAnimation.fromValue = fromValue;
 46     /*byvalue是在fromvalue的值的基礎上增加量*/
 47     //basicAnimation.byValue = @1;
 48     basicAnimation.toValue = toValue;
 49     basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];;
 50     basicAnimation.duration = 2;
 51     basicAnimation.repeatCount = 1;
 52     /* animation remove from view after animation finish */
 53     basicAnimation.removedOnCompletion = YES;
 54     return basicAnimation;
 55 }
 56 - (void)initData{
 57     /*
 58      kCAScaleZ 縮放z 沒有意義,因為是平面圖形
 59      kCAPositionX設置y沒有意義,可以隨意設置,同理kCAPositionY設置x沒有意義
 60      kCABackgroundColor,顏色變化必須要用CGColor
 61      用到shadow的幾個屬性變化的時候,需要先設置shadow
 62      */
 63     NSValue *startPoint = [NSValue valueWithCGPoint:self.squareView.center];
 64     NSValue *endPoint = [NSValue valueWithCGPoint:CGPointMake(500, 500)];
 65     NSValue *shadowStartPoint = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
 66     NSValue *shadowEndPoint = [NSValue valueWithCGPoint:CGPointMake(5, 5)];
 67     id startColor = (id)([UIColor cyanColor].CGColor);
 68     id endColor = (id)([UIColor redColor].CGColor);
 69     id shadowStartColor = (id)[UIColor clearColor].CGColor;
 70     id shadowEndColor = (id)[UIColor redColor].CGColor;
 71     self.dataSource = [NSMutableArray array];
 72     NSArray *keypaths   = @[kCARotation,kCARotationX,kCARotationY,kCARotationZ,
 73                             kCAScale,kCAScaleX,kCAScaleZ,kCAPositionX,
 74                             kCABoundsSizeW,kCAOpacity,kCABackgroundColor,kCACornerRadius,
 75                             kCABorderWidth,kCAShadowColor,kCAShadowRadius,kCAShadowOffset];
 76     
 77     NSArray *fromValues = @[@0,@0,@0,@0,
 78                             @0,@0,@0,startPoint,
 79                             @100,@1,startColor,@0,
 80                             @0,shadowStartColor,@0,shadowStartPoint];
 81     
 82     NSArray *toValues   = @[@(M_PI),@(M_PI),@(M_PI),@(M_PI),
 83                             @1,@1,@1,endPoint,
 84                             @200,@0,endColor,@40,
 85                             @4,shadowEndColor,@8,shadowEndPoint];
 86     for (int i=0; i<keypaths.count; i++) {
 87         AnimationModel *model = [[AnimationModel alloc] init];
 88         model.keyPaths = keypaths[i];
 89         model.fromValue = fromValues[i];
 90         model.toValue = toValues[i];
 91         [self.dataSource addObject:model];
 92     }
 93 }
 94 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
 95     return 1;
 96 }
 97 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
 98     return [self.dataSource count];
 99 }
100 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
101     AnimationModel *model = [self.dataSource objectAtIndex:indexPath.row];
102     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellID"];
103     if (cell==nil) {
104         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellID"];
105     }
106     cell.textLabel.text = model.keyPaths;
107     cell.selectionStyle = 0;
108     return cell;
109 }
110 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
111     AnimationModel *model = [self.dataSource objectAtIndex:indexPath.row];
112     CABasicAnimation *animation = [self getAnimationKeyPath:model.keyPaths fromValue:model.fromValue toValue:model.toValue];
113     [self.squareView.layer addAnimation:animation forKey:nil];
114 }
115 @end

  之所以在執行動畫的view上加入一個label,是為了測試當layer放大時其子類的變化。layer進行縮放時,它的大小並沒有發生改變,我們看到它變大或變小是因為它離我們的距離在發生改變,所以其子視圖會隨着一起變化。然而,改變其frame,它的大小和坐標是確實發生了改變,其子視圖正常情況下是不會發生變化的。CABasicAnimation用法非常簡單,下面介紹其子類CASpringAnimation。

二、CASpringAnimation

1.什么是CASpringAnimation

  CASpringAnimation是在CABasicAnimation的基礎上衍生的另一個動畫類,它比CABasicAnimation多了動畫的彈性,是動畫不再是從一個狀態變成另一個狀態時顯得生硬。CASpringAnimation是iOS9.0之后新加的。

2.新增屬性

  @property CGFloat mass;       //質量(影響彈簧的慣性,質量越大,彈簧慣性越大,運動的幅度越大)

  @property CGFloat stiffness;  //彈性系數(彈性系數越大,彈簧的運動越快)

  @property CGFloat damping;    //阻尼系數(阻尼系數越大,彈簧的停止越快)

  @property CGFloat initialVelocity;  //初始速率(彈簧動畫的初始速度大小,彈簧運動的初始方向與初始速率的正負一致,若初始速率為0,表示忽略該屬性)

  @property CGFloat settlingDuration; //結算時間(根據動畫參數估算彈簧開始運動到停止的時間,動畫設置的時間最好根據此時間來設置)

  這三個屬性可以設置動畫在執行到最終狀態后的彈性效果,具體值需要調試,下面給出一個具體的類來實現這一功能。

  1 #import "SpringAnimationView.h"
  2 #import "UIView+HPAdditions.h"
  3 
  4 @interface SpringAnimationView()<UITableViewDelegate,UITableViewDataSource>
  5 @property (nonatomic, strong) UIView *squareView;
  6 @property (nonatomic, strong) UITableView *tableView;
  7 @property (nonatomic, strong) NSMutableArray *dataSource;
  8 @property (nonatomic, strong) UISlider *massSlider;
  9 @property (nonatomic, strong) UISlider *stiffnessSlider;
 10 @property (nonatomic, strong) UISlider *dampingSlider;
 11 @property (nonatomic, strong) UILabel *massLabel;
 12 @property (nonatomic, strong) UILabel *stiffnessLabel;
 13 @property (nonatomic, strong) UILabel *dampingLabel;
 14 @end
 15 
 16 @implementation SpringAnimationView
 17 
 18 - (instancetype)init{
 19     if (self = [super initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]) {
 20         [self initData];
 21         [self setupUI];
 22     }
 23     return self;
 24 }
 25 - (void)setupUI{
 26     self.squareView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
 27     self.squareView.backgroundColor = [UIColor cyanColor];
 28     self.squareView.layer.borderColor = [UIColor redColor].CGColor;
 29     self.squareView.center = CGPointMake(SCREEN_WIDTH/2.0, 200);
 30     self.squareView.layer.shadowOpacity = 0.6;
 31     self.squareView.layer.shadowOffset = CGSizeMake(0, 0);
 32     self.squareView.layer.shadowRadius = 4;
 33     self.squareView.layer.shadowColor = [UIColor redColor].CGColor;
 34     [self addSubview:self.squareView];
 35     
 36     self.massSlider = [[UISlider alloc] initWithFrame:CGRectMake(20, 0, 100, 40)];
 37     self.massSlider.minimumValue = 0;
 38     self.massSlider.maximumValue = 1;
 39     self.massSlider.tintColor = [UIColor cyanColor];
 40     self.massSlider.thumbTintColor = [UIColor redColor];
 41     self.massSlider.top = self.squareView.bottom + 100;
 42     [self addSubview:self.massSlider];
 43     [self.massSlider addTarget:self action:@selector(durationChange:) forControlEvents:UIControlEventValueChanged];
 44     
 45     self.stiffnessSlider = [[UISlider alloc] initWithFrame:CGRectMake(20, 0, 100, 40)];
 46     self.stiffnessSlider.minimumValue = 0;
 47     self.stiffnessSlider.maximumValue = 100;
 48     self.stiffnessSlider.tintColor = [UIColor cyanColor];
 49     self.stiffnessSlider.thumbTintColor = [UIColor redColor];
 50     self.stiffnessSlider.top = self.massSlider.bottom + 10;
 51     [self addSubview:self.stiffnessSlider];
 52     [self.stiffnessSlider addTarget:self action:@selector(durationChange:) forControlEvents:UIControlEventValueChanged];
 53     
 54     self.dampingSlider = [[UISlider alloc] initWithFrame:CGRectMake(20, 0, 100, 40)];
 55     self.dampingSlider.minimumValue = 0;
 56     self.dampingSlider.maximumValue = 10;
 57     self.dampingSlider.tintColor = [UIColor cyanColor];
 58     self.dampingSlider.thumbTintColor = [UIColor redColor];
 59     self.dampingSlider.top = self.stiffnessSlider.bottom + 10;
 60     [self addSubview:self.dampingSlider];
 61     [self.dampingSlider addTarget:self action:@selector(durationChange:) forControlEvents:UIControlEventValueChanged];
 62     
 63     self.massLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
 64     self.massLabel.text = @"mass";
 65     self.massLabel.centerY = self.massSlider.centerY;
 66     self.massLabel.left = self.massSlider.right+10;
 67     self.massLabel.textAlignment = NSTextAlignmentLeft;
 68     self.massLabel.textColor = [UIColor blackColor];
 69     self.massLabel.font = [UIFont systemFontOfSize:17];
 70     [self addSubview:self.massLabel];
 71     
 72     self.stiffnessLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
 73     self.stiffnessLabel.text = @"stiffness";
 74     self.stiffnessLabel.centerY = self.stiffnessSlider.centerY;
 75     self.stiffnessLabel.left = self.stiffnessSlider.right+10;
 76     self.stiffnessLabel.textAlignment = NSTextAlignmentLeft;
 77     self.stiffnessLabel.textColor = [UIColor blackColor];
 78     self.stiffnessLabel.font = [UIFont systemFontOfSize:17];
 79     [self addSubview:self.stiffnessLabel];
 80     
 81     self.dampingLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
 82     self.dampingLabel.text = @"damping";
 83     self.dampingLabel.centerY = self.dampingSlider.centerY;
 84     self.dampingLabel.left = self.dampingSlider.right+10;
 85     self.dampingLabel.textAlignment = NSTextAlignmentLeft;
 86     self.dampingLabel.textColor = [UIColor blackColor];
 87     self.dampingLabel.font = [UIFont systemFontOfSize:17];
 88     [self addSubview:self.dampingLabel];
 89     
 90     self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, self.dampingSlider.bottom+20, SCREEN_WIDTH, SCREEN_HEIGHT-self.dampingSlider.bottom-20) style:UITableViewStylePlain];
 91     self.tableView.delegate = self;
 92     self.tableView.dataSource = self;
 93     [self addSubview:self.tableView];
 94 }
 95 
 96  /* The mass of the object attached to the end of the spring. Must be greater
 97  than 0. Defaults to one. */
 98 
 99 //@property CGFloat mass;
100 
101 /* The spring stiffness coefficient. Must be greater than 0.
102  * Defaults to 100. */
103 
104 //@property CGFloat stiffness;
105 
106 /* The damping coefficient. Must be greater than or equal to 0.
107  * Defaults to 10. */
108 
109 //@property CGFloat damping;
110 
111 /* The initial velocity of the object attached to the spring. Defaults
112  * to zero, which represents an unmoving object. Negative values
113  * represent the object moving away from the spring attachment point,
114  * positive values represent the object moving towards the spring
115  * attachment point. */
116 
117 //@property CGFloat initialVelocity;
118 
119 - (CASpringAnimation *)getAnimationKeyPath:(NSString *)keyPath fromValue:(id)fromValue toValue:(id)toValue{
120     CASpringAnimation *springAnimation = [CASpringAnimation animationWithKeyPath:keyPath];
121     springAnimation.fromValue = fromValue;
122     springAnimation.toValue = toValue;
123     springAnimation.mass = self.massSlider.value;
124     springAnimation.stiffness = self.stiffnessSlider.value;
125     springAnimation.damping = self.dampingSlider.value;
126     springAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];;
127     springAnimation.duration = 2;
128     springAnimation.repeatCount = 1;
129     /* animation remove from view after animation finish */
130     springAnimation.removedOnCompletion = YES;
131     /*
132      只有當removedOnCompletion設置為no時,fillmode設置為kCAFillModeBoth或者kCAFillModeForwards才有效,
133      kCAFillModeRemoved //動畫執行完成后回到初始狀態
134      kCAFillModeBackwards //動畫執行完成后回到初始狀態
135      kCAFillModeForwards //動畫執行完成后保留最后狀態
136      kCAFillModeBoth //動畫執行完成后保留最后狀態
137      */
138     springAnimation.fillMode = kCAFillModeForwards;
139     /*
140      動畫執行完成后按原動畫返回執行,default no
141      */
142 //    springAnimation.autoreverses = YES;
143     return springAnimation;
144 }
145 - (void)initData{
146     /*
147      kCAScaleZ 縮放z 沒有意義,因為是平面圖形
148      kCAPositionX設置y沒有意義,可以隨意設置,同理kCAPositionY設置x沒有意義
149      kCABackgroundColor,顏色變化必須要用CGColor
150      用到shadow的幾個屬性變化的時候,需要先設置shadow
151      */
152     NSValue *shadowStartPoint = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
153     NSValue *shadowEndPoint = [NSValue valueWithCGPoint:CGPointMake(5, 5)];
154     id startColor = (id)([UIColor cyanColor].CGColor);
155     id endColor = (id)([UIColor redColor].CGColor);
156     id shadowStartColor = (id)[UIColor clearColor].CGColor;
157     id shadowEndColor = (id)[UIColor redColor].CGColor;
158     self.dataSource = [NSMutableArray array];
159     NSArray *keypaths   = @[kCARotation,kCARotationX,kCARotationY,kCARotationZ,
160                             kCAScale,kCAScaleX,kCAScaleZ,kCAPositionY,
161                             kCABoundsSizeW,kCAOpacity,kCABackgroundColor,kCACornerRadius,
162                             kCABorderWidth,kCAShadowColor,kCAShadowRadius,kCAShadowOffset];
163     
164     NSArray *fromValues = @[@0,@0,@0,@0,
165                             @0,@0,@0,@0,
166                             @100,@1,startColor,@0,
167                             @0,shadowStartColor,@0,shadowStartPoint];
168     
169     NSArray *toValues   = @[@(M_PI),@(M_PI),@(M_PI),@(M_PI),
170                             @1,@1,@1,@400,
171                             @200,@0,endColor,@40,
172                             @4,shadowEndColor,@8,shadowEndPoint];
173     for (int i=0; i<keypaths.count; i++) {
174         AnimationModel *model = [[AnimationModel alloc] init];
175         model.keyPaths = keypaths[i];
176         model.fromValue = fromValues[i];
177         model.toValue = toValues[i];
178         [self.dataSource addObject:model];
179     }
180 }
181 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
182     return 1;
183 }
184 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
185     return [self.dataSource count];
186 }
187 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
188     AnimationModel *model = [self.dataSource objectAtIndex:indexPath.row];
189     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellID"];
190     if (cell==nil) {
191         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellID"];
192     }
193     cell.textLabel.text = model.keyPaths;
194     cell.selectionStyle = 0;
195     return cell;
196 }
197 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
198     [self.squareView.layer removeAllAnimations];
199     AnimationModel *model = [self.dataSource objectAtIndex:indexPath.row];
200     CABasicAnimation *animation = [self getAnimationKeyPath:model.keyPaths fromValue:model.fromValue toValue:model.toValue];
201     [self.squareView.layer addAnimation:animation forKey:@"animation"];
202 }
203 - (void)durationChange:(UISlider *)slider{
204     [slider setValue:slider.value];
205     if (slider==self.massSlider) {
206         self.massLabel.text = [NSString stringWithFormat:@"mass   %.2f", slider.value];
207     }else if (slider==self.stiffnessSlider) {
208         self.stiffnessLabel.text = [NSString stringWithFormat:@"stiffness   %.2f", slider.value];
209     }else if (slider==self.dampingSlider) {
210         self.dampingLabel.text = [NSString stringWithFormat:@"damping   %.2f", slider.value];
211     }
212 }
213 @end
214 
215 --------------------------------------------------------------------------------------
216 #import <UIKit/UIKit.h>
217 
218 @interface UIView (HPAdditions)
219 @property (nonatomic) CGFloat top;
220 @property (nonatomic) CGFloat bottom;
221 @property (nonatomic) CGFloat left;
222 @property (nonatomic) CGFloat right;
223 
224 @property (nonatomic) CGFloat width;
225 @property (nonatomic) CGFloat height;
226 @property (nonatomic) CGPoint origin;
227 @property (nonatomic) CGSize size;
228 
229 @property (nonatomic) CGFloat centerX;
230 @property (nonatomic) CGFloat centerY;
231 
232 @end
233 
234 #import "UIView+HPAdditions.h"
235 
236 @implementation UIView (HPAdditions)
237 - (CGFloat)top{
238     return self.frame.origin.y;
239 }
240 - (void)setTop:(CGFloat)top{
241     CGRect frame = self.frame;
242     frame.origin.y = top;
243     self.frame = frame;
244 }
245 - (CGFloat)bottom{
246     return self.frame.origin.y+self.frame.size.height;
247 }
248 - (void)setBottom:(CGFloat)bottom{
249     CGRect frame = self.frame;
250     frame.origin.y = bottom-frame.size.height;
251     self.frame = frame;
252 }
253 - (CGFloat)left{
254     return self.frame.origin.x;
255 }
256 - (void)setLeft:(CGFloat)left{
257     CGRect frame = self.frame;
258     frame.origin.x = left;
259     self.frame = frame;
260 }
261 - (CGFloat)right{
262     return self.frame.origin.x+self.frame.size.width;
263 }
264 - (void)setRight:(CGFloat)right{
265     CGRect frame = self.frame;
266     frame.origin.x = right-frame.size.width;
267     self.frame = frame;
268 }
269 
270 - (CGFloat)width{
271     return self.frame.size.width;
272 }
273 - (void)setWidth:(CGFloat)width{
274     CGRect frame = self.frame;
275     frame.size.width = width;
276     self.frame = frame;
277 }
278 - (CGFloat)height{
279     return self.frame.size.height;
280 }
281 - (void)setHeight:(CGFloat)height{
282     CGRect frame = self.frame;
283     frame.size.height = height;
284     self.frame = frame;
285 }
286 - (CGFloat)centerX{
287     return self.center.x;
288 }
289 - (void)setCenterX:(CGFloat)centerX{
290     self.center = CGPointMake(centerX, self.center.y);
291 }
292 - (CGFloat)centerY{
293     return self.center.y;
294 }
295 - (void)setCenterY:(CGFloat)centerY{
296     self.center = CGPointMake(self.center.x, centerY);
297 }
298 - (CGPoint)origin{
299     return self.frame.origin;
300 }
301 - (void)setOrigin:(CGPoint)origin{
302     CGRect frame = self.frame;
303     frame.origin = origin;
304     self.frame = frame;
305 }
306 - (CGSize)size{
307     return self.frame.size;
308 }
309 - (void)setSize:(CGSize)size{
310     CGRect frame = self.frame;
311     frame.size = size;
312     self.frame = frame;
313 }
314 
315 @end

   CABasicAnimation及其子類CASpringAnimation使用都是非常簡單的,CASpringAnimation能夠做出更加優雅的動畫,建議使用。但是這兩種動畫能過制作的動畫都是需要給定初始和最終狀態值的,而中間過程需要系統去處理,這樣的動畫比較單一,下一篇將會介紹添加中間過程的動畫CAKeyFrameAnimation關鍵幀動畫,它能做出更加炫酷的動畫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM