position 和 anchorPoint
都是CALayer的两个非常重要的属性
@proper CGPoinstposition
用来设置CALayer在父层中的位置
以父层的左上角为原点(0,0)
@proper CGPoinst anchorPoint
称为“定位点”、“锚点”
决定着CALayer身上的哪个点会再position属性使指的位置
以自己的左上角为原点(0,0)
它的x,y取值范围都是0~1,默认值为(0.5,0.5)
备注:实际上position点与anchorPoint点都是指向同一个点,只是相对的位置不一样,position点是相对父层的坐标系,而anchorPoint 是相对自己的坐标系,但是如果anchorPoint点的不同,显示的效果就不一样了,比如


隐式动画
- 每个
UIView
内部都默认关联一个CALayer,我么可称这个Layer为RootLayer(根层)
- 所有的
非RootLaye
r ,也就是手动创建
的CALayer对象,都存在着隐式动画
当对非RootLayer的部分属性进行修改
时,默认会自动产生一些动画效果
而这些属性称为Animation Properties(可动画属性)
常见的以下几种:
bounds
:用于设置CALayer的宽度和高度,修改这个属性会产生缩放动画
backgrounds
:用于设置CALayer的背景颜色,修改这个属性会产生背景颜色的渐变动画
position
:用于设置CALayer的位置,修改这个属性会产生平移动画
备注:
设置隐式动画执行时间
// 比如设置隐式动画执行时间是2秒
[CATransaction setAnimationDuration:2];
// 执行要修改的可动画属性:比如位移
self.myView.layer.position = CGPoint(10,10)
// 关闭隐式动画 YES:表示关闭隐式动画 NO:开启隐式动画
// 只要是setDisableActions:YES之后的可动画属性设置了,是没有隐式动画
[CATransaction setDisableActions:YES];
self.myView.layer.position = CGPoint(10,10)
// 动画事务CATranscation
// 动画的设置只对begin 和 commit之间的设置有效
// 比如设置位移的时候有隐式动画,修改背景颜色的时候关闭隐式动画
CATransaction begin];
[CATransaction setDisableActions:YES];
// 执行要修改的可动画属性
self.myView.layer.position = CGPointMake(10, 10);
[CATransaction commit];
self.myView.layer.background = [UIColor red].CGColor;
核心动画
Core Animation 核心动画
1>可以在Mac OS 和 iOS平台
2>Core Animation动画执行过程都是在后台操作
的,不会柱塞主线程
3>Core Animation是直接作用在CALayer上
的,并非UIView


CABaseAnimation

#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.imageView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 创建动画对象
CABasicAnimation *animation = [CABasicAnimation animation];
// 设置属性
animation.keyPath = @"transform.scale";
animation.toValue = @0;
// 设置动画执行次数
animation.repeatCount = MAXFLOAT;
// 设置动画执行时间
animation.duration = 1;
// 自动反转(怎么样去,怎么样回来)
animation.autoreverses = YES;
[self.imageView.layer addAnimation:animation forKey:nil];
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"测试"]];
_imageView.userInteractionEnabled = YES;
_imageView.image = [UIImage imageNamed:@"timg-2"];
_imageView.frame = CGRectMake(100, 100, 200, 200);
}
return _imageView;
}
@end
CAKeyframeAnimation

#import "ViewController.h"
#define angl2Rad(x) ((x)*M_PI/180)
@interface ViewController ()
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.imageView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 创建动画对象
CAKeyframeAnimation *animatino = [CAKeyframeAnimation animation];
// 设置属性值
animatino.keyPath = @"transform.rotation";
animatino.values = @[@(angl2Rad(-3)),@(angl2Rad(3)),@(angl2Rad(-3))];
// 设置动画执行次数
animatino.repeatCount = MAXFLOAT;
// 设置动画执行时间
animatino.duration = 0.5;
[self.imageView.layer addAnimation:animatino forKey:nil];
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"测试"]];
_imageView.userInteractionEnabled = YES;
_imageView.image = [UIImage imageNamed:@"timg-2"];
_imageView.frame = CGRectMake(100, 100, 200, 200);
}
return _imageView;
}
@end

#import "ViewController.h"
#define angl2Rad(x) ((x)*M_PI/180)
@interface ViewController ()
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.imageView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 创建动画对象
CAKeyframeAnimation *animatino = [CAKeyframeAnimation animation];
// 创建路径:使图片按照路径移动
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 200, 200)];
// 设置属性值
animatino.keyPath = @"position";
animatino.path = bezierPath.CGPath;
// 设置动画执行次数
animatino.repeatCount = MAXFLOAT;
// 设置动画执行时间
animatino.duration = 5;
[self.imageView.layer addAnimation:animatino forKey:nil];
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"测试"]];
_imageView.userInteractionEnabled = YES;
_imageView.image = [UIImage imageNamed:@"timg-2"];
_imageView.frame = CGRectMake(100, 100, 200, 200);
}
return _imageView;
}
@end
转场动画


@interface ViewController ()
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.imageView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
static NSInteger i = 1;
I++;
if (i==4) {
I=1;
}
NSString *imageName = [NSString stringWithFormat:@"%ld",I];
self.imageView.image = [UIImage imageNamed:imageName];
// 创建动画对象
CATransition *animation = [CATransition animation];
// 设置转场动画的效果
animation.type = @"pageUnCurl";
animation.duration = 1;
// 设置动画的起始位置
animation.startProgress = 0.3;
// 设置动画的结束位置
animation.endProgress = 0.8;
[self.imageView.layer addAnimation:animation forKey:nil];
// 注意点:
// 转场代码与转场动画必须得在同一个方法中
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc]initWithFrame:self.view.bounds];
_imageView.image = [UIImage imageNamed:@"1"];
_imageView.userInteractionEnabled = YES;
}
return _imageView;
}
@end
动画组(同时执行多个动画)

#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.imageView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CABasicAnimation *animation1 = [CABasicAnimation animation];
animation1.keyPath = @"position.y";
animation1.toValue = @(400);
CABasicAnimation *animation2 = [CABasicAnimation animation];
animation2.keyPath = @"transform.scale";
animation2.toValue = @(0.5);
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[animation1,animation2];
// 以下的设置都是对动画组内的所有动画都有效
// 如果想每个动画的设置不一样,则在创建动画对象的时候单独设置
// 动画执行时间
group.duration = 1;
// 动画结束后保持当前状态
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
[self.imageView.layer addAnimation:group forKey:nil];
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
_imageView.image = [UIImage imageNamed:@"1"];
_imageView.userInteractionEnabled = YES;
}
return _imageView;
}
@end
UIView与核心动画的区别?
1. 核心动画只作用在Layer
2. 核心动画看到的都是假象,它并没有修改UIView的真实位置(只修改layer的显示,这回导致UIView显示的位置与手势的作用域不一样)
什么时候使用核心动画?
1. 当不需要与用户进行交互,使用核心动画
2. 当要根据路径做动画时,使用核心动画
3. 当做转场动画时,使用核心动画(核心动画转场类型比较多,当荣UIView也是能先做转场动画的)
网友评论