CABasicAnimation使用总结
CABasicAnimation使用总结
实例化
使用方法animationWithKeyPath:对 CABasicAnimation进行实例化,并指定Layer的属性作为关键路径进行注册。
//围绕y轴旋转
CABasicAnimation *transformAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
设定动画
设定动画的属性和说明
| 属性 | 说明 |
|---|---|
| duration | 动画的时长 |
| repeatCount | 重复的次数。不停重复设置为 HUGE_VALF |
| repeatDuration | 设置动画的时间。在该时间内动画一直执行,不计次数。 |
| beginTime | 指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式 |
| timingFunction | 设置动画的速度变化 |
| autoreverses | 动画结束时是否执行逆动画 |
| fromValue | 所改变属性的起始值 |
| toValue | 所改变属性的结束时的值 |
| byValue | 所改变属性相同起始值的改变量 |
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两个属性就可以了。
transformAnima.removedOnCompletion = NO;
transformAnima.fillMode = kCAFillModeForwards;
解释:为什么动画结束后返回原状态?
首先我们需要搞明白一点的是,layer动画运行的过程是怎样的?其实在我们给一个视图添加layer动画时,真正移动并不是我们的视图本身,而是 presentation layer 的一个缓存。动画开始时 presentation layer开始移动,原始layer隐藏,动画结束时,presentation layer从屏幕上移除,原始layer显示。这就解释了为什么我们的视图在动画结束后又回到了原来的状态,因为它根本就没动过。
这个同样也可以解释为什么在动画移动过程中,我们为何不能对其进行任何操作。
所以在我们完成layer动画之后,最好将我们的layer属性设置为我们最终状态的属性,然后将presentation layer 移除掉。
添加动画
[self.imageView.layer addAnimation:transformAnima forKey:@"A"];
需要注意的两点
- 一个 CABasicAniamtion 的实例对象只是一个数据模型,和他绑定到哪一个layer上是没有关系的
- 方法
addAnimation:forKey:是将 CABasicAniamtion 对象进行了 copy 操作的。所以在将其添加到一个layer上之后,我们还是将其再次添加到另一个layer上的。
fillMode属性的理解
该属性定义了你的动画在开始和结束时的动作。默认值是 kCAFillModeRemoved。
取值的解释
- kCAFillModeRemoved 设置为该值,动画将在设置的 beginTime 开始执行(如没有设置beginTime属性,则动画立即执行),动画执行完成后将会layer的改变恢复原状。

- kCAFillModeForwards 设置为该值,动画即使之后layer的状态将保持在动画的最后一帧,而removedOnCompletion的默认属性值是 YES,所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO。

- kCAFillModeBackwards 设置为该值,将会立即执行动画的第一帧,不论是否设置了 beginTime属性。观察发现,设置该值,刚开始视图不见,还不知道应用在哪里。

- kCAFillModeBoth 该值是 kCAFillModeForwards 和 kCAFillModeBackwards的组合状态

Animation Easing的使用
也即是属性timingFunction值的设定,有种方式来获取属性值
(1)使用方法functionWithName:
这种方式很简单,这里只是简单说明一下取值的含义:
kCAMediaTimingFunctionLinear 传这个值,在整个动画时间内动画都是以一个相同的速度来改变。也就是匀速运动。
kCAMediaTimingFunctionEaseIn 使用该值,动画开始时会较慢,之后动画会加速。

kCAMediaTimingFunctionEaseOut 使用该值,动画在开始时会较快,之后动画速度减慢。

kCAMediaTimingFunctionEaseInEaseOut 使用该值,动画在开始和结束时速度较慢,中间时间段内速度较快。

(2)使用方法functionWithControlPoints: : : :实现,这个之后再说,占个坑先。
其他的一些设置属性
- repeatCount 设置动画的执行次数
- autoreverses 默认值为 NO,将其设置为 YES
- speed 改变动画的速度 可以直接设置动画上的speed属性,这样只有这个动画速度。
animation.speed = 2;
或者在layer上设置speed属性,这样在该视图上的所有动画都提速,该视图上的所有子视图上的动画也会提速。
speed两点需注意的:
(1) 如果设置动画时间为4s,speed设置为2,则动画只需2s即可执行完。
(2)如果同时设置了动画的speed和layer 的speed,则实际的speed为两者相乘。
使用总结
- 在动画执行完成之后,最好还是将动画移除掉。也就是尽量不要设置
removedOnCompletion属性为NO fillMode尽量取默认值就好了,不要去设置它的值。只有在极个别的情况下我们会修改它的值,以后会说到,这里先占个坑。- 解决有时视图会闪动一下的问题,我们可以将layer的属性值设置为我们的动画最后要达到的值,然后再给我们的视图添加layer动画。
例子(移动动画实现)
直接上代码
CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.duration = 0.8;
positionAnima.fromValue = @(self.imageView.center.y);
positionAnima.toValue = @(self.imageView.center.y-30);
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
positionAnima.repeatCount = HUGE_VALF;
positionAnima.repeatDuration = 2;
positionAnima.removedOnCompletion = NO;
positionAnima.fillMode = kCAFillModeForwards;
[self.imageView.layer addAnimation:positionAnima forKey:@"AnimationMoveY"];
组合动画的实现
CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.fromValue = @(self.imageView.center.y);
positionAnima.toValue = @(self.imageView.center.y-30);
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
CABasicAnimation *transformAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
transformAnima.fromValue = @(0);
transformAnima.toValue = @(M_PI);
transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
CAAnimationGroup *animaGroup = [CAAnimationGroup animation];
animaGroup.duration = 2.0f;
animaGroup.fillMode = kCAFillModeForwards;
animaGroup.removedOnCompletion = NO;
animaGroup.animations = @[positionAnima,transformAnima];
[self.imageView.layer addAnimation:animaGroup forKey:@"Animation"];
动画开始和结束时的事件
为了获取动画的开始和结束事件,需要实现协议
positionAnima.delegate = self;
代理方法实现
//动画开始时
- (void)animationDidStart:(CAAnimation *)anim
{
NSLog(@"开始了");
}
//动画结束时
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//方法中的flag参数表明了动画是自然结束还是被打断,比如调用了removeAnimationForKey:方法或removeAnimationForKey方法,flag为NO,如果是正常结束,flag为YES。
NSLog(@"结束了");
}
其实比较重要的是有多个动画的时候如何在代理方法中区分不同的动画
两种方式
方式一:
如果我们添加动画的视图是全局变量,可使用该方法。
添加动画时,我们使用了
[self.imageView.layer addAnimation:animaGroup forKey:@"Animation"];
所以,可根据key来区分不同的动画
//动画开始时
- (void)animationDidStart:(CAAnimation *)anim
{
if ([anim isEqual:[self.imageView.layer animationForKey:@"Animation"]]) {
NSLog(@"动画组执行了");
}
}
Note:把动画存储为一个属性然后再回调中比较,用来判定是哪个动画是不可行的。应为委托传入的动画参数是原始值的一个深拷贝,不是同一个值
方式二
添加动画的视图是局部变量时,可使用该方法
添加动画给动画设置key-value对
[positionAnima setValue:@"PositionAnima" forKey:@"AnimationKey"];
[transformAnima setValue:@"TransformAnima" forKey:@"AnimationKey"];
所以,可以根据key中不同的值来进行区分不同的动画
//动画结束时
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"PositionAnima"]) {
NSLog(@"位置移动动画执行结束");
}
else if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"TransformAnima"]){
NSLog(@"旋转动画执行结束");
}
}
解决循环引用问题
由于CAAnimation的delegate使用的strong类型,

所以在全局变量如下设置时会产生循环引用的情况
self.animation.delegate = self;//可通过复用dealloc方法来验证
解决方案
- 声明一个单独的类实现delegate的回调
//.h
#import <UIKit/UIKit.h>
@interface AnimationDelegate : NSObject
@end
//.m
#import "AnimationDelegate.h"
@implementation AnimationDelegate
- (void)animationDidStart:(CAAnimation *)anim
{
NSLog(@"Animation Start");
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
NSLog(@"Animation Stop");
}
- (void)dealloc
{
NSLog(@"Delegate Dealloc");
}
@end
使用方式
self.animation.delegate = [[AnimationDelegate alloc]init];
- 使用
NSProxy来解决
该类可直接引用YYKit中的YYWeakProxy类
使用方法
self.animation.delegate = [YYWeakProxy proxyWithTarget:self];
一些常用的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之间的 |
CABasicAnimation使用总结的更多相关文章
- 基本动画CABasicAnimation - 完成之后闪回初始状态
基本动画CABasicAnimation 结束之后,默认闪回初始状态,那怎么解决呢? position需要设备两个属性: // MARK: - 结束后不要闪回去 anim.removedOnCompl ...
- CABasicAnimation的基本使用方法(移动·旋转·放大·缩小)
出处:http://blog.csdn.net/iosevanhuang/article/details/14488239 CABasicAnimation类的使用方式就是基本的关键帧动画. 所谓关键 ...
- CABasicAnimation的delegate的坑
博客已经迁移到 www.chjsun.top 在自定义动画的时候,CABasicAnimation用的还算的蛮多的. 在此先介绍一下CABasicAnimation怎么使用. 属性介绍 属性 说明 ...
- 之一:CABasicAnimation - 基本动画
嗷呜嗷呜嗷呜 // 将视图作为属性方便后面执行多个不同动画 _myView = [[UIView alloc] init]; _myView.layer.position = CGPointMake( ...
- iOS - CABasicAnimation
代码实例: [1] - (void)pulseClick { //!> 宽和高等比例转换 CABasicAnimation * pulse = [CABasicAnimation animati ...
- 核心动画基础动画(CABasicAnimation)关键帧动画
1.在iOS中核心动画分为几类: 基础动画(CABasicAnimation) 关键帧动画(CAKeyframeAnimation) 动画组(CAAnimationGroup) 转场动画(CATran ...
- CABasicAnimation 按home键后台之后,再切回来动画就停止了
解决方法: 1. CABasicAnimation *thisAnimation = [CABasicAnimtaion animationWithKeyPath:@"transform.r ...
- CABasicAnimation animationWithKeyPath 一些规定的值
CABasicAnimation animationWithKeyPath Types When using the ‘CABasicAnimation’ from the QuartzCore Fr ...
- IOS第18天(5,CABasicAnimation基本动画)
******* #import "HMViewController.h" @interface HMViewController () @property (nonatomic, ...
- 动画 CABasicAnimation animationWithKeyPath 一些规定的值
CABasicAnimation animationWithKeyPath Types When using the ‘CABasicAnimation’ from the QuartzCore Fr ...
随机推荐
- Android中使用异步线程更新UI视图的几种方法
在Android中子线程是不能更新ui的. 所以我们要通过其他方式来动态改变ui视图, 1.runOnUiThreadactivity提供的一个轻量级更新ui的方法,在Fragment需要使用的时候要 ...
- Python 装饰器的总结
先来了解几个定义: 1,函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: #coding:UTF8 ...
- python之复数
#coding=utf8 ''''' 复数是由一个实数和一个虚数组合构成,表示为:x+yj 一个负数时一对有序浮点数(x,y),其中x是实数部分,y是虚数部分. Python语言中有关负数的概念: 1 ...
- mysql那些招
show table status mysql官方文档在 http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html 这里的rows行是 ...
- 理解 Java 正则表达式怪异的 \\ 和 \\\\,让您见怪不怪
本文链接 https://unmi.cc/understand-java-regex-backslash/, 来自 隔叶黄莺 Unmi Blog Java 语言里的几大变革,一为 jdk1.4 引入的 ...
- Python学习---django多对多自定义第三方表180206
案例一: # version: python3.2.5 # author: 'FTL1012' # time: 2018/2/6 16:25 from django.db import models ...
- setfacl 命令的常用用法
setfacl命令----可以用来细分linux下的文件权限. chmod命令----可以把文件权限分为u,g,o三个组,而setfacl可以对每一个文件或目录设置更精确的文件权限. 换句话说,set ...
- MP4个人制作
- Python3基本数据类型(二、字符串)
Python3字符串 ①字符串比较 1.比较字符串是否相同: ==:使用==来比较两个字符串内的value值是否相同 is:比较两个字符串的id值. 2.字符串的长度比较 len():显示字符串的长度 ...
- myeclipse解决JSP文件里script背景颜色的调整
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/UP19910522/article/details/27971401 1导入MyEclipse的主题 ...


