iOS 动画-购物车动画为例

设定动画

设定动画的属性和说明

属性 说明
duration 动画的时长
repeatCount 重复的次数。不停重复设置为 HUGE_VALF
repeatDuration 设置动画的时间。在该时间内动画一直执行,不计次数。
beginTime 指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式
timingFunction 设置动画的速度变化
autoreverses 动画结束时是否执行逆动画
fromValue 所改变属性的起始值
toValue 所改变属性的结束时的值
byValue 所改变属性相同起始值的改变量
1
2
3
4
5
6
transformAnima.fromValue = @(M_PI_2);
transformAnima.toValue = @(M_PI);
transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transformAnima.autoreverses = YES;
transformAnima.repeatCount = HUGE_VALF;
transformAnima.beginTime = CACurrentMediaTime() + 2;

防止动画结束后回到初始状态

只需设置removedOnCompletion、fillMode两个属性就可以了

1
2
transformAnima.removedOnCompletion = NO;
transformAnima.fillMode = kCAFillModeForwards;

一些常用的animationWithKeyPath值的总结

说明 使用形式
transform.scale 比例转化 @(0.8)
transform.scale.x 宽的比例 @(0.8)
transform.scale.y 高的比例 @(0.8)
transform.rotation.x 围绕x轴旋转 @(M_PI)
transform.rotation.y 围绕y轴旋转 @(M_PI)
transform.rotation.z 围绕z轴旋转 @(M_PI)
cornerRadius 圆角的设置 @(50)
backgroundColor 背景颜色的变化 (id)[UIColor purpleColor].CGColor
bounds 大小,中心不变 [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
position 位置(中心点的改变) [NSValue valueWithCGPoint:CGPointMake(300, 300)];
contents 内容,比如UIImageView的图片 imageAnima.toValue = (id)[UIImage imageNamed:@”to”].CGImage;
opacity 透明度 @(0.7)
contentsRect.size.width 横向拉伸缩放 @(0.4)最好是0~1之间的

购物车动画

ShoppingCarAnimationTool.h定义屏幕信息和block回传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define ScreenHeight [UIScreen mainScreen].bounds.size.height

typedef void(^AnimationFinishBlock)(BOOL finishBlock);
// 添加属性
@property (nonatomic, strong) CALayer *layer;
@property (nonatomic, copy) AnimationFinishBlock animationFinishBlock;
// 暴露出来的方法
// 初始化
+ (instancetype)shareTool;

/**
* 开始动画
* @param view 添加动画的view
* @param rect view 的绝对frame
* @param finishPoint 下落的位置
* @param completion 动画完成回调
*/
- (void)startAnimationandView:(UIView *)view andRect:(CGRect)rect andFinisnRect:(CGPoint)finishPoint andFinishBlock:(AnimationFinishBlock)completion;

// 摇晃动画
+ (void)shakeAnimation:(UIView *)shakeView;

ShoppingCarAnimationTool.m实现方法
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
+ (instancetype)shareTool{
return [[ShoppingCarAnimationTool alloc] init];
}

- (void)startAnimationandView:(UIView *)view andRect:(CGRect)rect andFinisnRect:(CGPoint)finishPoint andFinishBlock:(AnimationFinishBlock)completion{
//------- 创建CALayer -------//
_layer = [CALayer layer];
_layer.contents = view.layer.contents;
_layer.contentsGravity = kCAGravityResizeAspectFill;
rect.size.width = 60;
rect.size.height = 60; //重置图层尺寸
_layer.bounds = rect;
_layer.cornerRadius = rect.size.width/2;
_layer.masksToBounds = YES; //圆角
// 添加layer到顶层视图控制器上
[[UIApplication sharedApplication].delegate.window.layer addSublayer:_layer];

_layer.position = CGPointMake(rect.origin.x + view.frame.size.width/2, CGRectGetMidY(rect)); //a 点
//------- 创建移动轨迹 -------/
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:_layer.position];
[path addQuadCurveToPoint:finishPoint controlPoint:CGPointMake(ScreenWidth/2, rect.origin.y - 80)];
//关键帧动画
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.path = path.CGPath;
// 旋转动画
CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotateAnimation.removedOnCompletion = YES;
rotateAnimation.fromValue = [NSNumber numberWithFloat:0];
rotateAnimation.toValue = [NSNumber numberWithFloat:12];
rotateAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

CAAnimationGroup *groups = [CAAnimationGroup animation];
groups.animations = @[pathAnimation, rotateAnimation];
groups.duration = 1.2f;
groups.removedOnCompletion = NO;
groups.fillMode = kCAFillModeForwards;
groups.delegate = self;
[_layer addAnimation:groups forKey:@"group"];
if (completion) {
_animationFinishBlock = completion;
}
}

// 动画结束代理
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (anim == [_layer animationForKey:@"group"]) {
[_layer removeFromSuperlayer];
_layer = nil;
if (_animationFinishBlock) {
_animationFinishBlock(YES);
}
}
}

// 上下晃动动画
+ (void)shakeAnimation:(UIView *)shakeView{
CABasicAnimation *shakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
shakeAnimation.duration = 0.25;
shakeAnimation.fromValue = [NSNumber numberWithFloat:-5];
shakeAnimation.toValue = [NSNumber numberWithFloat:5];
shakeAnimation.autoreverses = YES;
[shakeView.layer addAnimation:shakeAnimation forKey:nil];
}

-------------本文结束感谢您的阅读-------------
最近的文章

iOS 瀑布流布局实现详解

新建文件继承自UICollectionViewLayout.h内容如下:1234567891011121314151617181920@class WaterFlowLayout;@protocol WaterFlowLayoutDelegate <NSObject>/&#x2 …

继续阅读
更早的文章

iOS 中UIWebView与WKWebView

1. UIWebViewUIWebView 适用于iOS8.0以下的系统版本iOS原生没有提供js直接调用OC的方式,只能通过UIWebView的UIWebViewDelegate协议方法来做拦截,并在这个方法中,根据url来调用OC方法;1-(BOOL)webView:(UIWebView *)w …

继续阅读