周老师的QuartzCore教程 - 专用图层(上)

2018-03-26  本文已影响33人  muchDrinkHotWat

专用图层(上)

CALayer的孩子们

专用图层是CALayer的子类,各自具有不同的功能,使用之后能够进一步扩展使用Core Animation绘图的能力。

专用图层的绘制通常是使用硬件加速完成的,通常会具有较好的性能。且相较于使用UIView实现相应效果,CALayer会自带隐式动画,能有更为流畅的变化效果。

目录

CAShapeLayer - 矢量图层

属性

通过CGPath绘制图形

CAGradientLayer - 渐变图层

属性

基础渐变

多重渐变

基于渐变图层的一些的特效

小结

CAShapeLayer - 矢量图层

在上一节中,我们已经初步使用过CAShapeLayerCAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类,可以指定颜色 线宽等属性,用path属性定义需要绘制的图形。相比较于通过使用Core Graphics进行绘制,他具有以下优点:

path属性是一个CGPathRef类型对象,可以由(UIBezierPath *)path.CGPath转换获得

属性

以上是最常用的属性

strokeEndstrokeStart属性通常用于做动画,比如你可以试一下

[NSTimer scheduledTimerWithTimeInterval:0.01 repeats:YES block:^(NSTimer * _Nonnull timer) {
        shapeLayer.strokeStart += 0.005;
}];

你会看到你的Path慢慢的就变短了。

[写到此处周老师忽然意识到进度条可以用这个东西来写]

下图从上到下依次为kCALineCapButt kCALineCapRound kCALineCapSquare样式。

kCALineCapButt样式上和kCGLineCapButt是一样的,但是长度会长一丢丢

1.2.png

下图从上到下依次为kCALineJoinMiter kCALineJoinRound kCALineJoinBevel样式。此时miterLimit的值足够大,故会有一个很长很长的斜角。

1.3.png
//设置虚线数组为[2,5,10],数组会按数组元素循环截断线条(2pt为红,5pt为透明,10pt为红,2pt为白.....)
shapeLayer.lineDashPattern = @[@2, @5, @10];
//lineDashPhase的动画属性,能够事实更改并生效
[NSTimer scheduledTimerWithTimeInterval:0.02 repeats:YES block:^(NSTimer * _Nonnull timer) {
  shapeLayer.lineDashPhase += 1;
}];
1.4.gif

通过CGPath绘制图形

CAShapeLayer能够绘制所有可以通过CGPath来表示的形状,不论闭合与否,且可以在一个图层上绘制多个不同的形状。其次可以控制一些属性比如lineWith(线宽,用点表示单位),lineCap(线条结尾的样子),和lineJoin(线条之间的结合点的样子);但是在一个图层中,所有这些属性只能有一个样式,所以你如果想用不同的颜色/粗细/风格来绘制多个形状,那就需要使用多个图层。

接下来是用CAShapeLayer绘制一个火柴人的例子:

UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(175, 100)];
//下面是画图的代码
[path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
[path moveToPoint:CGPointMake(150, 125)];
[path addLineToPoint:CGPointMake(150, 175)];
[path addLineToPoint:CGPointMake(125, 225)];
[path moveToPoint:CGPointMake(150, 175)];
[path addLineToPoint:CGPointMake(175, 225)];
[path moveToPoint:CGPointMake(100, 150)];
[path addLineToPoint:CGPointMake(200, 150)];
//创建shapeLayer,配置属性
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor redColor].CGColor;//线条颜色为红色
shapeLayer.fillColor = [UIColor clearColor].CGColor;//填充颜色为透明,否则会对线条包围的部分进行填充
shapeLayer.lineWidth = 5;
shapeLayer.lineJoin = kCALineJoinRound;//圆形折角
shapeLayer.lineCap = kCALineCapRound;//圆形断点
shapeLayer.path = path.CGPath;
//添加至superLayer后生效
[self.view.layer addSublayer:shapeLayer];
1.1.png

CAGradientLayer - 渐变图层

CAGradientLayer是用来生成两种或更多颜色平滑渐变的,绘制使用了硬件加速,同时也可以用Core Graphics复制一个CAGradientLayer并将内容绘制到一个普通图层的寄宿图。

属性

例:设置startPoint为{0, 0.5},endPoint为{1, 0.5},渐变轴的方向

2.1.jpg

基础渐变

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(100, 100, 200, 200);
[self.view.layer addSublayer:gradientLayer];
//设置渐变颜色为[红, 蓝]
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id)[UIColor blueColor].CGColor];
//设置起点为左上角,重点为右下角
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
2.2.png

多重渐变

colors属性可以包含很多颜色,locations属性定义了这些颜色的位置(沿轴线分布的距离)。

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(100, 100, 200, 200);
[self.view.layer addSublayer:gradientLayer];
    
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
                         (__bridge id) [UIColor yellowColor].CGColor,
                         (__bridge id)[UIColor greenColor].CGColor];
gradientLayer.locations = @[@0.0, @0.25, @0.5];
    
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
2.3.png

一些骚骚的特效

虽然渐变图层看起来土土的还很乡非,但是配合其他绘制机制,可以组合变化出一些很酷炫的操作。

比如配合蒙板可以实现:

2.4.gif

这个效果的原理是:渐变图层做渐变动画,使用一个UILabel.layer作为蒙板,达到文字发生渐变的效果。

2.5.gif
//创建渐变图层
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[self.view.layer addSublayer:gradientLayer];
gradientLayer.frame = CGRectMake(0, 200, kScreenWidth, 64);
//设置渐变轴为从左往右
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
//黑白相间的颜色
gradientLayer.colors = @[
                         (__bridge id)[UIColor blackColor].CGColor,
                         (__bridge id)[UIColor whiteColor].CGColor,
                         (__bridge id)[UIColor blackColor].CGColor,];
//因为要做动画,所以locations属性可以是任何NSArray对象就可以了
//甚至你可以这样写: .locations = @[@"干死黄旭东", @"蟑螂加两攻"];
//下面是规范写法
gradientLayer.locations = @[@0.25,@0.5,@0.75];

//添加动画
//动画KeyPath指定为"locations",表示要对gradientLayer.locations属性做动画
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"locations"];
basicAnimation.fromValue = @[@0, @0, @0.25];
basicAnimation.toValue = @[@0.75, @1, @1];
basicAnimation.duration = 2.5;
basicAnimation.repeatCount = HUGE;
[gradientLayer addAnimation:basicAnimation forKey:nil];

//接下来创建作为蒙板的Label
//注意这个frame,是相对gradientLayer的坐标
UILabel *label = [[UILabel alloc] initWithFrame:gradientLayer.bounds];
label.text = @"滑动狗头解锁 >>";
label.alpha = 0.5;
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:30];
//一定要强引用这个Label避免被释放
self.label = label;
//重点:设置Label的layer为gradientLayer的蒙板,不需要做addSubView操作
gradientLayer.mask = label.layer;

小结

CAShapeLayerCAGradientLayer都是具有绘制作用的专用图层,而且他们的绘制都是使用硬件加速完成的,他们通常能够以相对较高的性能完成一些简单的绘制和显示效果工作。例如在日常工作中遇到需要做简单填充效果的时候,可以使用专用图层来替代Core Graphics提升性能,而且由于CALayer带有隐式动画,还可以省去动画调度代码的编写。

上一篇 下一篇

猜你喜欢

热点阅读