前言
上一篇已经介绍了核心动画在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关键帧动画,它能做出更加炫酷的动画。
来源:https://www.cnblogs.com/lmfboke/p/8582705.html