一.基本使用
UIView中有一个layer的属性, 系统中的定义如下:
@property(nonatomic,readonly,strong)CALayer *layer;
// returns view's layer. Will always return a non-nil value. view is layer's delegate
这个layer就是UIView中的图层.UIView本身不具备显示的功能,拥有显示功能的是它内部的图层.换句话说,UIView本神显示的功能就是由这个layer来完成的.这个CALayer能够对UIView做很多显示上的设定,比如边框,圆角阴影等等.
CALayer是个与UIView很类似的概念,同样有layer,sublayer...,同样有backgroundColor、frame等相似的属性,我们可以将UIView看做一种特殊的CALayer,只不过UIView可以响应事件而已。
关于CALayer:
首先:
1.CALayer是定义在QuartzCore框架中的
2.CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的
3.UIColor、UIImage是定义在UIKit框架中的
其次:
1.QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用
2.但是UIKit只能在iOS中使用
3.为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef
我感觉CALayer和UIView相比,CALayer更加轻量级,他们两个之间的区别也就是一个能响应用户事件,一个不能响应用户事件.
所以在处理不需要用户响应的事件时,用CALayer性能会更加好,不过在手机性能更好的现在,我认为只要手机处理你的软件时,只要不会卡顿,引起用户体验上的不足时,随意用哪个都行.
UIView *view = [[UIView alloc]init];
// 边框宽度
view.layer.borderWidth = 10;
// 边框颜色,这里由于CALayer是系统底层的缘故,不能直接使用IOS中的UI属性的对象,要将UIColor属性转换成CGColor属性,
view.layer.borderColor = [UIColor greenColor].CGColor;
// 圆角
view.layer.cornerRadius = 10;
// 是否切割视图之外的部分 类似UIView的clipsToBounds
view.layer.masksToBounds = YES;
// 阴影颜色
view.layer.shadowColor = [UIColor redColor].CGColor;
// 阴影偏差
view.layer.shadowOffset = CGSizeMake(20, 20);
// 阴影不透明度
view.layer.shadowOpacity = 0.5;
//这个是layer的transform属性,在系统中的定义是CATransform3D,这个属性请看我最下面的解释:
view.layer.transform = CATransform3DMakeScale(1.5, 0.5, 0);
//旋转
view.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
//这个是view的transform属性,在系统中的定义是CGAffineTransform,这句的意思就是旋转
view.transform = CGAffineTransformMakeRotation(M_PI_4);
//利用KVC给layer属性赋值,但是CATransform3DMakeRotation是个结构体,不能直接赋值,需要先包装成NSValue进行赋值
NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)];
[view.layer setValue:value forKeyPath:@"transform"];
//旋转
[view.layer setValue:@(M_PI_2) forKeyPath:@"transform.rotation"];
//比例缩放
view.layer.transform = CATransform3DMakeScale(0.5, 2, 0);
[view.layer setValue:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.5, 2, 0)] forKeyPath:@"transform"];
// 可以传递哪些key path, 在官方文档搜索 "CATransform3D key paths"
[view.layer setValue:@(-100) forKeyPath:@"transform.translation.x"];
这里附上transform的属性列表:(可以暂时跳过这里往后看)
这里需要提到的时CALayer有2个非常重要的属性:position和anchorPoint
@property CGPoint position;
用来设置CALayer在父层中的位置
以父层的左上角为原点(0, 0)
@property CGPoint anchorPoint;
称为“定位点”.“锚点”
决定着CALayer身上的哪个点会在position属性所指的位置
以自己的左上角为原点(0, 0)
它的x y取值范围都是0~1,默认值为(0.5,0.5)
关于这个定位点,我在下面也有详细的解释,不过也是在网上找到的,比我自己解释要详细,容易懂.
关于CALyer还有一个重要的特性:隐式动画
每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层),所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画.
那么什么是隐式动画?当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果,而这些属性称为Animatable Properties(可动画属性)例如:
bounds:这个属性是用来设置CALayer的宽高的,修改这个属性会产生动画效果.
backgroundColor:这个属性设置背景颜色,修改这个会有渐变的效果
position:这个属性设置CALayer的的位置,修改这个会有移动的效果
可以通过动画事务(CATransaction)关闭默认的隐式动画效果
[CATransaction begin];
[CATransaction setDisableActions:YES];
self.myview.layer.position = CGPointMake(10, 10);
[CATransaction commit];
图层的创建
如果将要创建图层可以仿照我这下面的代码设置,图层只能放在图层上,CALayer我前面说过,与UIView很类似,用法也大同小异
CALayer *layer = [CALayer layer];
layer.backgroundColor = [UIColor redColor].CGColor;
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.position = CGPointMake(200, 100);
layer.cornerRadius = 10;
layer.masksToBounds = YES;
layer.contents = (id)[UIImage imageNamed:@""].CGImage;//设置图片也要将IOS中的UI控件转化为底层的属性
[self.view.layer addSublayer:layer];
自定义图层,建立好图层后,如果想在图层中绘图需要实现代理方法,IOS中图层的代理方法是对NSObject协议的分类扩展,意味着所有的继承于NSObject的对象都遵循了这个协议,在定义图层layer的类中可以直接实现.
CALayer *layer = [CALayer layer];
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.backgroundColor = [UIColor blackColor].CGColor;
layer.anchorPoint = CGPointZero;
layer.position = CGPointMake(100, 100);
layer.delegate = self; //设置代理
[layer setNeedsDisplay]; //这个方法是异步执行的.setNeedsDisplay会自动调用drawRect方法,这样可以拿到UIGraphicsGetCurrentContext,就可以画画了.关于这个方法的使用可以看看这篇博客http://blog.sina.com.cn/s/blog_923fdd9b0101b2b4.html,详细介绍了这个方法会调用的方法,会怎样调用.
[self.view.layer addSublayer:layer];
#pragma mark - 图层的代理方法
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
CGContextAddRect(ctx, CGRectMake(0, 0, 20, 20));
CGContextFillPath(ctx);
}
这里详细说明下view的完整显示过程
1. view.layer会准备一个Layer Graphics Contex(图层类型的上下文)
2. 调用view.layer.delegate(view)的drawLayer:inContext:,并传入刚才准备好的上下文
3. view的drawLayer:inContext:方法内部又会调用view的drawRect:方法
4. view就可以在drawRect:方法中实现绘图代码, 所有东西最终都绘制到view.layer上面
5. 系统再将view.layer的内容拷贝到屏幕, 于是完成了view的显示
二.核心动画使用
CAAnimation的继承关系如上.(我从网上找来的截图)
Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程
CAAnimation是所有动画类的父类,但是它不能直接使用,应该使用它的子类。
常见属性有:
duration:动画的持续时间
repeatCount:动画的重复次数
timingFunction:控制动画运行的节奏
CAAnimation能用的动画类只有上述说明的几个子类:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup
(CAPropertyAnimation算CABasicAnimation、CAKeyframeAnimation这两个的父类)
CAPropertyAnimation是CAAnimation的子类,但是不能直接使用,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
它有个NSString类型的keyPath属性,你可以指定CALayer的某个属性名为keyPath,并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@"position"为keyPath,就会修改CALayer的position属性的值,以达到平移的动画效果
1.CABasicAnimation
通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
2.CAKeyframeAnimation
Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动
3.CAAnimationGroup
Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时执行,如何按顺序执行我到时候再讲。
4.CATransition
这个就是苹果帮开发者封装好的一些动画,也叫做转场动画,效果不多,但是挺不错的.
CAAnimation的使用步骤
1.使用它需要先添加QuartzCore.framework框架和引入主头文件<QuartzCore/QuartzCore.h>(iOS7不需要)
2.初始化一个CAAnimation对象,并设置一些动画相关属性
3.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画
CABasicAnimation
平移动画:
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];
// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
anim.keyPath = @"position";
// anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
// fromValue : 从什么值开始变化
// toValue : 最终变成什么值
// byValue : 增加多少值,步进值
anim.byValue = [NSValue valueWithCGPoint:CGPointMake(200, 300)];
anim.duration = 2.0;
/**让图层保持动画执行完毕后的状态**/
// 动画执行完毕后不要删除动画
anim.removedOnCompletion = NO;
// 保持最新的状态,不写这句代码,动画执行完会回到原始位置.
anim.fillMode = kCAFillModeForwards;
// 3.添加动画,将动画添加进自己创建的图层中
[self.layer addAnimation:anim forKey:nil];
缩放动画:
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];
// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
anim.keyPath = @"bounds";
// anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
anim.duration = 2.0;
/**让图层保持动画执行完毕后的状态**/
// 动画执行完毕后不要删除动画
anim.removedOnCompletion = NO;
// 保持最新的状态
anim.fillMode = kCAFillModeForwards;
// 3.添加动画
[self.layer addAnimation:anim forKey:nil];
旋转动画:
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];
// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
anim.keyPath = @"transform";
// anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, -1, 0)];
anim.duration = 2.0;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
// 3.添加动画
[self.layer addAnimation:anim forKey:nil];
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];
// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
anim.keyPath = @"transform";
//anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, -1, 0)];
anim.duration = 2.0;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
// 3.添加动画
[self.layer addAnimation:anim forKey:nil];
以上都是CABasicAnimationde的基本动画
CABasicAnimation算是CAKeyFrameAnimation的特殊情况(最多只有2个关键帧的CAKeyframeAnimation),即不考虑中间变换过程,只考虑起始点与目标点就可以了。而CAKeyFrameAnimation则更复杂一些,允许我们在起点与终点间自定义更多内容来达到我们的实际应用需求,KeyFrame的意思是关键帧,所谓“关键”就是改变物体运动趋势的帧,在该点处物体将发生运动状态,比如矩形的四个角,抛物线的顶点等
CAKeyframeAnimation
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"position";
NSValue *v1 = [NSValue valueWithCGPoint:CGPointZero];
NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 0)];
NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)];
anim.values = @[v1, v2, v3, v4];
//anim.keyTimes = @[@(0.5), @(0.25), @(0.25)];这句给每个动画分别设置动画时间,如果不设置,系统默认平均分配时间
anim.duration = 2.0;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
[self.redView.layer addAnimation:anim forKey:nil];
按照指定的路径移动
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"position";
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
anim.duration = 2.0;
CGMutablePathRef path = CGPathCreateMutable();//圆形的路径
CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 200, 200));//这个CGRect设置的时路径起始位置和旋转的饿上下半径;
anim.path = path;
CGPathRelease(path);
// 设置动画的执行节奏
// kCAMediaTimingFunctionEaseInEaseOut : 一开始比较慢, 中间会加速, 临近结束的时候, 会变慢
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.delegate = self;
[self.redView.layer addAnimation:anim forKey:nil];
- (CAAnimation*)pathAnimation
{
/**
CAKeyframeAnimation
在画线的时候,方法的内部默认创建一个path。它把路径都放到了path里面去。
1.创建路径 CGMutablePathRef 调用该方法相当于创建了一个路径,这个路径用来保存绘图信息。
2.把绘图信息添加到路径里边。
以前的方法是点的位置添加到ctx(图形上下文信息)中,ctx 默认会在内部创建一个path用来保存绘图信息。
在图形上下文中有一块存储空间专门用来存储绘图信息,其实这块空间就是CGMutablePathRef。
3.把路径添加到上下文中。
*/
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,NULL,50.0,120.0);
CGPathAddLineToPoint(path, NULL, 300, 488);
CGPathAddCurveToPoint(path,NULL,50.0,275.0,150.0,275.0,150.0,120.0);
CGPathAddCurveToPoint(path,NULL,150.0,275.0,250.0,275.0,250.0,120.0);
CGPathAddCurveToPoint(path,NULL,250.0,275.0,350.0,275.0,350.0,120.0);
CGPathAddCurveToPoint(path,NULL,350.0,275.0,450.0,275.0,450.0,120.0);
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[animation setPath:path];
[animation setDuration:3.0];
CFRelease(path);
//ARC的诞生大大简化了我们针对内存管理的开发工作,但是只支持管理 Objective-C 对象, 不支持 Core Foundation 对象。Core Foundation 对象必须使用CFRetain和CFRelease来进行内存管理
//http://blog.csdn.net/yiyaaixuexi/article/details/8553659
return animation;
}
这里解释下:
所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
属性解析:(来自CAMediaTiming协议的属性)
duration:动画的持续时间
repeatCount:动画的重复次数
repeatDuration:动画的重复时间
fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间
(非CAMediaTiming协议的属性)
removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
timingFunction:速度控制函数,控制动画运行的节奏
delegate:动画代理
CAKeyFrameAnimation的使用中有以下主要的属性需要注意
(1)values属性
values属性指明整个动画过程中的关键帧点。需要注意的是,起点必须作为values的第一个值。不然动画会有一个跳跃的过程,说白了就是你的图像在静止时是你设定的位置,但是动画启动时,这个图像回突然之间跳跃的另外一个位置开始动画,不知道我这样说,你们会不会懂.
(2)path属性
作用与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略。例如上述pathAnimation例子
(3)keyTimes属性
该属性是一个数组,用以指定每个子路径(AB,BC,CD)的时间。如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的1\4。当然,我们也可以传个数组让物体快慢结合。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7.....
(4)timeFunctions属性
用过UIKit层动画的同学应该对这个属性不陌生,这个属性用以指定时间函数,类似于运动的加速度,有以下几种类型。上例子的AB段就是用了淡入淡出效果。记住,这是一个数组,你有几个子路径就应该传入几个元素
1 kCAMediaTimingFunctionLinear//线性
2 kCAMediaTimingFunctionEaseIn//淡入
3 kCAMediaTimingFunctionEaseOut//淡出
4 kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
5 kCAMediaTimingFunctionDefault//默认
(5)calculationMode属性
该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似
1 const kCAAnimationLinear//线性,默认
2 const kCAAnimationDiscrete//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上
3 const kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
4 const kCAAnimationCubic//平均,同上
5 const kCAAnimationCubicPaced//平均,同上
CAAnimationGroup
// 1.创建旋转动画对象
CABasicAnimation *rotate = [CABasicAnimation animation];
rotate.keyPath = @"transform.rotation";
rotate.toValue = @(M_PI);
// 2.创建缩放动画对象
CABasicAnimation *scale = [CABasicAnimation animation];
scale.keyPath = @"transform.scale";
scale.toValue = @(0.0);
// 3.平移动画
// CABasicAnimation *move = [CABasicAnimation animation];
// move.keyPath = @"transform.translation";
// move.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
CAKeyframeAnimation *move = [CAKeyframeAnimation animation];
move.keyPath = @"transform.translation";
NSValue *v1 = [NSValue valueWithCGPoint:CGPointZero];
NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 0)];
// NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
// NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)];
move.values = @[v1, v2];
// 4.将所有的动画添加到动画组中
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[rotate, scale, move];
group.duration = 2.0;
group.removedOnCompletion = YES;
group.fillMode = kCAFillModeForwards;
[self.myvie.layer addAnimation:group forKey:nil];
CATransition
动画类型
fade 淡出效果
moveIn 新视图移动到旧视图
push 新视图推出旧视图
reveal 移开旧视图
cube 立方体翻转效果
oglFlip 翻转效果
suckEffect 收缩效果
rippleEffect 水滴波纹效果
pageCurl 向下翻页
pageUnCurl 向上翻页
-(CATransition *)createTransitionAnimation
{
//切换之前添加动画效果
//后面知识: Core Animation 核心动画
//不要写成: CATransaction
//创建CATransition动画对象
CATransition *animation = [CATransition animation];
//设置动画的类型:
animation.type = @"rippleEffect";
//设置动画的方向
animation.subtype = kCATransitionFromBottom;
//设置动画的持续时间
animation.duration = 1.5;
//设置动画速率(可变的)
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//动画添加到切换的过程中
return animation;
}
//添加动画
[self.view.layer addAnimation:[self createTransitionAnimation] forKey:nil];
动画的暂停与开始可以通过下面的方式做到:
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
这个方法是UINavigationControllerDelegate,返回的是Navagation的切换动画,在这里面可以设置navigation的转场动画
HUAnimator是一个转场动画的第三方库,感觉效果挺好的,可以自己在github上自行搜索下载看看
#pragma mark - UINavigationControllerDelegate
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
HUTransitionAnimator * animator = [[HUTransitionVerticalLinesAnimator alloc] init];
return animator;
}
这个是UIViewController切换的动画代理方法
@protocol UIViewControllerTransitioningDelegate <NSObject>
@optional
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;
- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator;
- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator;
- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0);
@end
解释:
这段CATransform3D是我在网上找到的,解释的很详细;
原文博客:http://blog.sina.com.cn/s/blog_8f5097be0101b91z.html
CATransform3D
CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
sx:X轴缩放,代表一个缩放比例,一般都是 0 --- 1 之间的数字。
sy:Y轴缩放。
sz:整体比例变换时,也就是m11(sx)== m22(sy)时,若m33(sz)>1,图形整体缩小,若0<1,图形整体放大,若m33(sz)<0,发生关于原点的对称等比变换。
当sx = 1,sy = 1时。如图:
当sx = 0.5,sy = 0.5时。如图:
CATransform3DMakeRotatio
旋转效果。
angle:旋转的弧度,所以要把角度转换成弧度:角度 * M_PI / 180。
x:向X轴方向旋转。值范围-1 --- 1之间
y:向Y轴方向旋转。值范围-1 --- 1之间
z:向Z轴方向旋转。值范围-1 --- 1之间
例:向X轴旋转60度。
向 X轴,Y轴都旋转60度,就是沿着对角线旋转。
可以通过X,Y,Z轴同时变化,来旋转图像。
CATransform3DInvert (CATransform3D t);
翻转效果。
CGAffineTransform CATransform3DGetAffineTr
bool CATransform3DIsAffine (CATransform3D t);
仿射效果。
就是把一个 CATransform3D 对象转换成一个 CGAffineTransform 对象。
也就是把 CATransform3D 矩阵 转换成 CGAffineTransform 矩阵
变换函数同时提供了可以比较一个变换矩阵是否是单位矩阵,或者两个矩阵是否相等。
bool CATransform3DIsIdentity (CATransform3D t);
bool CATransform3DEqualToTran
对于anchorPoint的解释在ios中如图:
position:是一个CGPoint值,它指定图层相当于它父图层的位置,该值基于父图层的坐标系。
bounds:是一个CGRect值,指定图层的大小(bounds.size)和图层的原点(bounds.origin),这个坐标系是基于自身的。如果改变bounds的origin,那么在该图层的子图层,坐标会跟着改变。也就是说,改变自身的坐标系,本身在父图层的位置不变,但它上的子图层位置变化。
anchorPoint:是一个CGPoint值,它是指定了一个基于bounds的符合坐标系的位置。锚点(anchor point)制定了bounds相对于position的值,同时也作为一个变化时候的中心点。锚点使用空间坐标系取值范围是0-1之间的数。默认是0.5,也就是秃瓢的中心点,如果是(0,0)那么,图层向左上方移动。如果是(1,1)就向右下方移动。
下图中的红点位置就是 锚点的位置:默认为(0.5,0.5)。在对图像进行变换时,都是按照这个点来进行缩放,偏移等。
一旦修改锚点的位置为:(0,0),那么图像就会变成下图。各种变换就会按照这个点来运动。
所以说,在ios系统中,锚点的坐标系是:左上角为(0,0),右下角为(1,1)。
根据此图,在理解上面的定义,就直观了一些。
下面这段是CALayer的代理方法
是对NSObject的一种扩展,意味着所有集成于NSObject的对象都能实现这个代理方法,并且默认已经遵守协议了
@interface NSObject (CALayerDelegate)
/* If defined, called by the default implementation of the -display
* method, in which case it should implement the entire display
* process (typically by setting the `contents' property). */
- (void)displayLayer:(CALayer *)layer;
/* If defined, called by the default implementation of -drawInContext: */
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
/* Called by the default -layoutSublayers implementation before the layout
* manager is checked. Note that if the delegate method is invoked, the
* layout manager will be ignored. */
- (void)layoutSublayersOfLayer:(CALayer *)layer;
/* If defined, called by the default implementation of the
* -actionForKey: method. Should return an object implementating the
* CAAction protocol. May return 'nil' if the delegate doesn't specify
* a behavior for the current event. Returning the null object (i.e.
* '[NSNull null]') explicitly forces no further search. (I.e. the
* +defaultActionForKey: method will not be called.) */
- (nullable id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event;
@end