layer的属性
每一个视图能显示出来,都是因为有layer存在。该对象有两个比较重要的属性:position和anchorPoint,第一个属性代表该视图相对于父控件的位置,第二个属性表示该视图上的哪个点会移动到对应的位置,它的取值范围是0到1.默认是0.5即视图中心。
自定义layer的方法
在创建的继承自CALayer的类里重写- (void)drawInContext:(CGContextRef)ctx 方法
// 重写该方法, 在该方法中给layer上绘制图形
// 注意CALayer中的drawInContext方法, 不会自动调用
// 只能自己通过setNeedDisplay方法调用
- (void)drawInContext:(CGContextRef)ctx
{
// 1.绘制图形
CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));
// [[UIColor redColor] set]; // 注意不能用UIKit框架中的类
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
// 1.渲染图形
CGContextFillPath(ctx);
}
CALayer *myLayer = [CALayer layer];
myLayer.delegate = self;
// 通过代理自定义layer
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
// 1.绘制图形
CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 50, 100));
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
// 1.渲染图形
CGContextFillPath(ctx);
}
隐式动画
所有的非根layer都存在隐式动画。当对非根层的部分属性进行修改时,会自动带有动画。这称之为隐式动画。
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CALayer *layer = [CALayer layer];
layer.backgroundColor = [UIColor redColor].CGColor;
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.anchorPoint = CGPointZero;
[self.view.layer addSublayer:layer];
self.layer = layer;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 关闭隐式动画
// [CATransaction begin];
// [CATransaction setDisableActions:YES];
// 隐式动画
self.layer.backgroundColor = [UIColor greenColor].CGColor;
// self.layer.bounds = CGRectMake(0, 0, 200, 200);
self.layer.position = CGPointMake(200, 200);
// self.layer.position // 如何查看CALayer的某个属性是否支持隐式动画, 查看头文件是否有 Animatable
// [CATransaction commit];
}
核心动画 CoreAnimation
它是一个跨平台的,该动画不会阻塞主线程,在后台操作
基础动画:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1. 创建核心动画
CABasicAnimation *anima = [CABasicAnimation animation] ;
// 1.1设置动画类型
// anima.keyPath = @"transform.translation.x";
anima.keyPath = @"transform.scale.y";
// 1.2 设置动画执行完毕之后不删除动画
anima.removedOnCompletion = NO;
// 1.3 设置保存动画的最新状态
anima.fillMode = kCAFillModeForwards;
// 1.4设置动画时间
anima.duration = 1;
// 1.5如何动画
// anima.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, 100, 1)];
// anima.toValue = @(100);
anima.toValue = @(1.5);
// 2.添加核心动画到Layer
[self.myLayer addAnimation:anima forKey:nil];
}
关键帧动画:
- (void)test1
{
// 1.创建核心动画
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
// 1.1告诉系统执行什么动画
keyAnima.keyPath = @"position";
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 100, 200, 200));
keyAnima.path = path;
CGPathRelease(path);
// 1.2保存执行完之后的状态
// 1.2.1执行完之后不删除动画
keyAnima.removedOnCompletion = NO;
// 1.2.2执行完之后保存最新的状态
keyAnima.fillMode = kCAFillModeForwards;
// 1.3设置动画时间
keyAnima.duration = 2;
// 2.观察动画什么时候开始执行, 以及什么时候执行完毕
keyAnima.delegate = self;
// 3.添加核心动画
[self.customView.layer addAnimation:keyAnima forKey:@"abc"];
}
- (void)test
{
// 1.创建核心动画
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
// 1.1告诉系统执行什么动画
keyAnima.keyPath = @"position";
// NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(0, 100)];
NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)];
NSValue *v5 = [NSValue valueWithCGPoint:CGPointMake(0, 100)];
keyAnima.values = @[v2, v3, v4, v5];
//用来设置每一小段动画的时间
// keyAnima.keyTimes = @[@(0.5) ,@(0.5), @(0.5)];
keyAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// 1.2保存执行完之后的状态
// 1.2.1执行完之后不删除动画
keyAnima.removedOnCompletion = NO;
// 1.2.2执行完之后保存最新的状态
keyAnima.fillMode = kCAFillModeForwards;
// 1.3设置动画时间
keyAnima.duration = 2;
// 2.观察动画什么时候开始执行, 以及什么时候执行完毕
keyAnima.delegate = self;
// 2.添加核心动画
[self.customView.layer addAnimation:keyAnima forKey:nil];
}
可以实现动画的代理方法来看动画什么时候执行,什么时候执行结束
用关键帧动画实现一个图标抖动:
#define angle2Radian(angle) ((angle) / 180.0 * M_PI)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.创建核心动画
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
keyAnima.keyPath = @"transform.rotation";
// 度数 / 180 * M_PI
keyAnima.values = @[@(-angle2Radian(4)), @(angle2Radian(4)), @(-angle2Radian(4))];
keyAnima.removedOnCompletion = NO;
keyAnima.fillMode = kCAFillModeForwards;
keyAnima.duration = 0.1;
// 设置动画重复的次数
keyAnima.repeatCount = MAXFLOAT;
// 2.添加核心动画
[self.iconView.layer addAnimation:keyAnima forKey:nil];
}
转场动画
// 1.创建核心动画
CATransition *ca = [CATransition animation];
// 1.1动画过渡类型
ca.type = @"cube";
// 1.2动画过渡方向
ca.subtype = kCATransitionFromRight;
// 1.3动画起点(在整体动画的百分比)
// ca.startProgress = 0.5;
ca.endProgress = 0.5;
// 动画时间
ca.duration = 1;
// 2.添加核心动画
[self.iconView.layer addAnimation:ca forKey:nil];
/* 过渡效果
fade //交叉淡化过渡(不支持过渡方向) kCATransitionFade
push //新视图把旧视图推出去 kCATransitionPush
moveIn //新视图移到旧视图上面 kCATransitionMoveIn
reveal //将旧视图移开,显示下面的新视图 kCATransitionReveal
cube //立方体翻滚效果
oglFlip //上下左右翻转效果
suckEffect //收缩效果,如一块布被抽走(不支持过渡方向)
rippleEffect //滴水效果(不支持过渡方向)
pageCurl //向上翻页效果
pageUnCurl //向下翻页效果
cameraIrisHollowOpen //相机镜头打开效果(不支持过渡方向)
cameraIrisHollowClose //相机镜头关上效果(不支持过渡方向)
*/
/* 过渡方向
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromBottom
kCATransitionFromTop*/
CATransition*anim = [CATransition animation];
anim.type =@“cube”; // 动画过渡类型
anim.subtype =kCATransitionFromTop; // 动画过渡方向
anim.duration =1; // 动画持续1s
//代理,动画执行完毕后会调用delegate的animationDidStop:finished:
anim.delegate= self;
/*******中间穿插改变layer属性的代码**********/
[layeraddAnimation:anim forKey:nil];
组动画
// 平移动画
CABasicAnimation *a1 = [CABasicAnimation animation];
a1.keyPath = @"transform.translation.y";
a1.toValue = @(100);
// 缩放动画
CABasicAnimation *a2 = [CABasicAnimation animation];
a2.keyPath = @"transform.scale";
a2.toValue = @(0.0);
// 旋转动画
CABasicAnimation *a3 = [CABasicAnimation animation];
a3.keyPath = @"transform.rotation";
a3.toValue = @(M_PI_2);
// 组动画
CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
groupAnima.animations = @[a1, a2, a3];
groupAnima.duration = 2;
groupAnima.fillMode = kCAFillModeForwards;
groupAnima.removedOnCompletion = NO;
[self.iconView.layer addAnimation:groupAnima forKey:nil];
核心动画与uiview封装的动画的区别:核心动画不会改变view的实际位置,而uiview封装的动画会 改变
UIView封装的转场动画
[UIView transitionWithView:self.view duration:1.0 options:0 animations:^{
NSLog(@"animations");
// 要执行的动画
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
} completion:^(BOOL finished) {
NSLog(@"completion");
// 执行完毕之后执行的动画
}];