您的位置:首页 > 其它

CALayer和核心动画

2015-12-22 12:08 295 查看
iOS里面一个View的可见是因为内部的一个CALayer类型的layer属性,能够响应事件是因为继承了UIResponder类。当UIView需要显示在屏幕上的时候会调用drawRect:方法进行

绘图,绘图完毕后系统会将图层拷贝到屏幕上,完成显示。

通过操作CALayer对象可以很方便的操作UIView的一些外观属性,还可以给图层添加动画来实现一些比较炫酷的效果。

常用的属性包含以下:@property CGRect bounds;

/* 宽高 The position in the superlayer that the anchor point of the layer's
* bounds rect is aligned to. Defaults to the zero point. Animatable. */

@property CGPoint position;
/* 中心位置,The Z component of the layer's position in its superlayer. Defaults
* to zero. Animatable. */
@property CGPoint anchorPoint;
/*
这个属性比较重要,锚点决定了那layer的某个点出现在position的位置。

The Z component of the layer's anchor point (i.e. reference point for
* position and transform). Defaults to zero. Animatable. */
@property(nullable) CGColorRef backgroundColor;

/* 背景颜色
When positive, the background of the layer will be drawn with
* rounded corners. Also effects the mask generated by the
* `masksToBounds' property. Defaults to zero. Animatable. */
@property CGFloat cornerRadius;

/*
切圆角
The width of the layer's border, inset from the layer bounds. The
* border is composited above the layer's content and sublayers and
* includes the effects of the `cornerRadius' property. Defaults to
* zero. Animatable. */

@property CGFloat borderWidth;

/* The color of the layer's border. Defaults to opaque black. Colors
* created from tiled patterns are supported. Animatable. */

@property(nullable) CGColorRef borderColor;

/* The opacity of the layer, as a value between zero and one. Defaults
* to one. Specifying a value outside the [0,1] range will give undefined
* results. Animatable. */


当设置某些控件发现圆角不起作用的时候要考虑,控件不仅仅有一个layer,显示内容不是在主层上面,应该考虑 self.myView.layer.masksToBounds设置为YES,使得超过主层的部分给清除,但是操作这里的时候阴影自然也就被清除了,如果要保证既有阴影,又无压力的切圆角,可以采用其他措施,比如可以用Quartz
2D方法生成一个圆角的图片然后再用。
layer支持3D效果的旋转,第一个参数表示旋转的角度,后面3个是x,y,z的坐标,表示沿着从原点到坐标(x,y,z)所在的直线的轴进行旋转,如果依然想沿着手机屏幕旋转只需要沿着z轴旋转就可以了,


layer的创建


1.直接使用CALayer创建

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;
//这个属性是id类型,可以添加的不仅仅是image
layer.contents = (id)[UIImage imageNamed:@"one"].CGImage;
[self.view.layer addSublayer:layer];


上面这种创建的layer无需强制调用setNeedsDisplay方法就可以显示。

@property(nullable, weak) id delegate;


这是layer的代理的定义,是一个id类型的,表示任何类都可以当成他的代理,而且任何类都已经存在他的代理方法。只要在代理类重写下面方法后,然后layer再调用

setNeedsDisplay,就可以自动调用下面的方法实现绘图功能,

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx



2.自己定义的layer继承CALayer。

这个时候要在自定义的layer类里面在下面方法添加代码

- (void)drawInContext:(CGContextRef)ctx


的ctx参数就是当前图层的上下文,在UIView里面的drawRect 方法里面常常用来绘制当前view的图层,需要下面代码来获取上下文

CGContextRef ctx = UIGraphicsGetCurrentContext();

通过自定义继承的图层使用的时候,


CALayer的隐式动画

每个UIView内部都有一个CALayer,所有的手动创建的CALayer对象(非创建View的时候带的layer),当对他的部分属性进行修改的时候默认会产生一些动画效果,这些属性称为

//    [CATransaction begin]; // 开启事务
//    [CATransaction setDisableActions:YES];

//这里修改会触发隐式动画的属性将不再触发隐式动画

//    [CATransaction commit]; // 提交事务



Core Animation(核心动画)

除了隐式动画外,CALayer可以手动的添加动画,动画是一个类,只要要创建一个动画,然后设置该动画的属性,把动画添加到图层上就能实现动画效果

CALayer中很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、contents等(可以在API文档中搜索:CALayer Animatable Properties) 通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就能触发动画了。通过调用removeAnimationForKey可以停止层中的动画 Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。

一共有4种常用的动画类,继承了CAAnimation,CAAnimation是抽象类,不能直接使用,继承结构如下:



所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类

属性解析:(红色代表来自CAMediaTiming协议的属性)

duration:动画的持续时间

repeatCount:动画的重复次数

repeatDuration:动画的重复时间

removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards

fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后

beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

timingFunction:速度控制函数,控制动画运行的节奏

delegate:动画代理

主要的步骤就是:

初始化一个动画对象,并设置一些动画的相关属性,添加动画到层中,开始执行动画。


CABasicAnimation

//移动
- (void)testTransform
{
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];

// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
//    anim.keyPath = @"transform.rotation";
//    anim.keyPath = @"transform.scale.x";
anim.keyPath = @"transform.translation.x";
anim.toValue = @(100);
//    anim.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
anim.duration = 2.0;

anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;

// 3.添加动画
[self.layer addAnimation:anim forKey:nil];
}
//旋转
- (void)testRotate
{
// 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];
}
//缩放
- (void)testScale
{
// 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];
}

//移动
- (void)testTranslate
{
// 1.创建动画对象
CABasicAnimation *anim = [CABasicAnimation animation];

// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪个属性来执行动画
anim.keyPath = @"position";
//    anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
// toValue : 最终变成什么值
// byValue : 增加多少值
anim.byValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
anim.duration = 2.0;

/**让图层保持动画执行完毕后的状态**/
// 动画执行完毕后不要删除动画
anim.removedOnCompletion = NO;
// 保持最新的状态
anim.fillMode = kCAFillModeForwards;

// 3.添加动画
[self.layer addAnimation:anim forKey:nil];
}



CAKeyframeAnimation

CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasic Animation只能从一个数值(fromValue)变到另一个数值(toValue),CAKeyframeAnimation会使用一个NSArray保存这些数值。

values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧

path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略

keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是

平分的 CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation

//抖动效果
- (void)shake {
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];

float angle = angle2radian(3);

anim.values = @[@(-angle), @(angle), @(-angle)];

anim.duration = 0.2;

anim.repeatCount = MAXFLOAT;

[self.myview.layer addAnimation:anim forKey:nil];
}
//移动
- (void)translate2 {
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 300, 300));
anim.duration = 2;
anim.path = path;

[self.myview.layer addAnimation:anim forKey:nil];

CGPathRelease(path);
}
//移动
- (void)translate {
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 设置动画执行的一个节奏
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
anim.duration = 2;

NSValue *p1 = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(300, 0)];
NSValue *p3 = [NSValue valueWithCGPoint:CGPointMake(300, 300)];
NSValue *p4 = [NSValue valueWithCGPoint:CGPointMake(0, 300)];

anim.values = @[p1, p2, p3, p4];

[self.myview.layer addAnimation:anim forKey:nil];
}




CATransition

用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果


type:动画过渡类型

subtype:动画过渡方向

startProgress:动画起点(在整体动画的百分比)

endProgress:动画终点(在整体动画的百分比)

CATransition *anim = [CATransition animation];
// 动画类型
anim.type = @"pageCurl";
// 过渡方向
anim.subtype = kCATransitionFromRight;
anim.duration = 0.5;
[self.imageView.layer addAnimation:anim forKey:nil];


  type的意义

pageCurl 向上翻一页
pageUnCurl 向下翻一页
rippleEffect 滴水效果
suckEffect 收缩效果,如一块布被抽走
cube 立方体效果
oglFlip 上下翻转效果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: