Dawninest

Objective-C | 动画

UIView动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[UIView animateWithDuration:1 delay:1 options:UIViewAnimationOptionCurveLinear animations:^{
xxx
} completion:^(BOOL finished) {
xxx
}];
animateWithDuration-动画持续时间
delay-动画延迟时间
options-动画渐入渐出
动画线性效果选择-options
UIViewAnimationOptionCurveEaseInOut 匀加速-匀速-匀减速
UIViewAnimationOptionCurveEaseIn 匀加速-匀速
UIViewAnimationOptionCurveEaseOut 匀速-匀减速
UIViewAnimationOptionCurveLinear 匀速
animations-在动画持续时间内执行的变幻
completion-该动画持续时间结束后执行的下一步动作,可在此嵌套下一步动画

缩放

1
_animationView.transform = CGAffineTransformScale(_animationView.transform, 0.5, 0.5);

旋转

1
_animationView.transform = CGAffineTransformRotate(_animationView.transform, M_PI_4);

变换动作-翻转

1
2
3
4
5
6
[UIView transitionWithView:_animationView duration:1 options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];

options 多个可用 | 间隔
翻转独有线性效果选项
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight

弹性动画

1
2
3
4
5
6
7
8
usingSpringWithDamping 阻尼系数 0-1 越小越明显
initialSpringVelocity 初始速度

[UIView animateWithDuration:0.2 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:0 animations:^{

} completion:^(BOOL finished){

}];

补充

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
UIViewAnimationOptions详细
UIViewAnimationOptionLayoutSubviews //动画过程中保证子视图跟随运动
UIViewAnimationOptionAllowUserInteraction //动画时允许用户交流,比如触摸
UIViewAnimationOptionBeginFromCurrentState //所有视图从当前状态开始动画
UIViewAnimationOptionRepeat //动画无限重复
UIViewAnimationOptionAutoreverse //动画运行到结束点后仍然以动画方式回到初始点,前提是设置动画无限重复
UIViewAnimationOptionOverrideInheritedDuration //忽略外层动画嵌套的执行时间
UIViewAnimationOptionOverrideInheritedCurve //忽略外层动画嵌套的时间变化曲线
UIViewAnimationOptionAllowAnimatedContent //通过改变属性和重绘实现动画效果,如果key没有提交动画将使用快照
UIViewAnimationOptionShowHideTransitionViews //用显隐的方式替代添加移除图层的动画效果
UIViewAnimationOptionOverrideInheritedOptions //不继承父动画设置或动画类型
时间函数曲线相关
UIViewAnimationOptionCurveEaseInOut //时间曲线函数,由慢到快
UIViewAnimationOptionCurveEaseIn //时间曲线函数,由慢到特别快
UIViewAnimationOptionCurveEaseOut //时间曲线函数,由快到慢
UIViewAnimationOptionCurveLinear //时间曲线函数,匀速
转场动画相关的
UIViewAnimationOptionTransitionNone //无转场动画
UIViewAnimationOptionTransitionFlipFromLeft //转场从左翻转
UIViewAnimationOptionTransitionFlipFromRight //转场从右翻转
UIViewAnimationOptionTransitionCurlUp //上卷转场
UIViewAnimationOptionTransitionCurlDown //下卷转场
UIViewAnimationOptionTransitionCrossDissolve //转场交叉消失
UIViewAnimationOptionTransitionFlipFromTop //转场从上翻转
UIViewAnimationOptionTransitionFlipFromBottom //转场从下翻转
关键帧
UIViewKeyframeAnimationOptionCalculationModeLinear    
UIViewKeyframeAnimationOptionCalculationModeDiscrete  
UIViewKeyframeAnimationOptionCalculationModePaced     
UIViewKeyframeAnimationOptionCalculationModeCubic     
UIViewKeyframeAnimationOptionCalculationModeCubicPaced

高级动画

CALayer 图层

初始化

1
2
3
4
5
6
7
8
9
10
11
12
@property (nonatomic,strong) CALayer *layer;
_layer = [CALayer layer];
_layer.backgroundColor = [UIColor colorWithRed:0.91 green:0.34 blue:0.31 alpha:1].CGColor;
_layer.bounds = CGRectMake(0, 0, 50, 50);
_layer.position = self.view.center;//设置中旬点
_layer.shadowColor = [UIColor colorWithRed:0.21 green:0.6 blue:0.93 alpha:1].CGColor;
_layer.shadowOffset = CGSizeMake(3, 3);
_layer.shadowOpacity = 0.8; 透明度
设置锚点,锚点的位置永远和中心点重合
默认(0.5,0.5),即中心点,按照比例取值,(0,0)左上角,(1,1)右下角
_layer.anchorPoint = CGPointMake(1, 1);
[self.view.layer addSublayer:_layer];

重写触摸事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
UITouch *touch = touches.anyObject;
CGPoint touchPoint = [touch locationInView:self.view];
CGFloat width = _layer.bounds.size.width;
if (width == 50) {
width = 50 * 4;
}else{
width = 50;
}
_layer.bounds = CGRectMake(0, 0, width, width);
_layer.position = touchPoint;
}
在使用CALayer 图层动画的时候,初始化之后的属性变化会自动以动画形式展现

CATransition 过渡动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CATransition *animation = [CATransition animation];
持续时间
animation.duration = 0.5;
线性规律
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
/*私有API 不可用于上架
cube、suckEffect、oglFlip、rippleEffect、pageCurl、pageUnCurl
cameraIrisHollowOpen、cameraIrisHollowClose
*/
animation.type = @"rippleEffect";
过渡动画类型 kCATransition
kCATransitionFade
kCATransitionMoveIn
kCATransitionPush
kCATransitionReveal
animation.type = kCATransitionPush;

配置转场动画子类型
animation.subtype = kCATransitionFromLeft;
添加动画
[self.view.layer addAnimation:animation forKey:@"transition"];

CABasicAnimation 基础动画

先确定基础动画的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
持续时间
positionAnimation.duration = 0.5;
运动线性
positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
动画的初始值-默认初始化的属性
positionAnimation.fromValue = [NSValue valueWithCGPoint:self.view.center];
动画的终止值
positionAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(self.view.bounds), 100)];
动画完成后是否回到原位,默认yes
positionAnimation.removedOnCompletion = NO;
positionAnimation.fillMode = kCAFillModeBoth;
决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态.
kCAFillModeBackwards 在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始. 你可以这样设定测试代码,将一个动画加入一个layer的时候延迟5秒执行.然后就会发现在动画没有开始的时候,只要动画被加入了layer,layer便处于动画初始状态
kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状
添加动画
[self.view.layer addAnimation:positionAnimation forKey:@"position"];

animationWithKeyPath可选类型有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
transform.scale  比例转换
transform.scale.x 宽的比例轉換
transform.scale.y 高的比例轉換
transform.rotation.z 平面园的旋轉
opacity 透明度
margin 边缘
zPosition
backgroundColor    背景颜色
cornerRadius    圆角
borderWidth 边框宽度
bounds 大小
contents 内容
contentsRect 内容矩形
cornerRadius 圆角半径
frame 位置及尺寸
hidden 隐藏
mask 遮罩
masksToBounds 遮住边界
position 位置
shadowColor 阴影颜色
shadowOffset 阴影偏移
shadowOpacity 阴影透明度
shadowRadius 阴影半径

CAKeyframeAnimation 关键帧动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CAKeyframeAnimation *keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
keyFrameAnimation.duration = 2;
keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
利用贝塞尔曲线绘制动画路径
UIBezierPath *path = [UIBezierPath bezierPath];
曲线起点
[path moveToPoint:self.view.center];
曲线轨迹(运动中将经过的点)
[path addLineToPoint:CPM(MID_X, MID_Y + 200)];
[path addLineToPoint:CPM(MID_X + 100, MID_Y + 200)];
闭合路径
[path addLineToPoint:CPM(MID_X + 100, MID_Y + 0)];
设置动画的路径
keyFrameAnimation.path = path.CGPath;
keyFrameAnimation.removedOnCompletion = NO;
keyFrameAnimation.fillMode = kCAFillModeForwards;
配置关键帧的时间控制-按照比例分配每一段运动轨迹时间
keyFrameAnimation.keyTimes = @[@"0.0",@"0.5",@"0.75",@"1.0"];

[self.view.layer addAnimation:keyFrameAnimation forKey:@"position"];

CAAnimationGroup 动画组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
例:组合两个基础动画
动画1
CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
positionAnimation.fromValue = [NSValue valueWithCGPoint:self.view.center];
positionAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(self.view.bounds), 100)];
动画2
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.fromValue = @(1.0);
opacityAnimation.toValue = @(0.4);
动画组
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[positionAnimation,opacityAnimation];
group.duration = 1;
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
[self.view.layer addAnimation:group forKey:@"group"];

渐变色

1
2
3
4
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.view.bounds;
gradientLayer.colors = @[(__bridge id)[UIColor colorWithRed:1.00 green:0.56 blue:0.00 alpha:1.00].CGColor,(__bridge id)[UIColor colorWithRed:0.26 green:0.79 blue:0.52 alpha:1.00].CGColor];
[self.view.layer addSublayer:gradientLayer];