前言
上一篇已經介紹了核心動畫在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關鍵幀動畫,它能做出更加炫酷的動畫。
