CAShapeLayer相关内容

CAShapeLayer是CALayer的子类

@interface CAShapeLayer : CALayer

在苹果官方的描述是:

 The CAShapeLayer class draws a cubic Bezier spline in its coordinate space. The shape is composited between the layer's contents and its first sublayer.

The shape will be drawn antialiased, and whenever possible it will be mapped into screen space before being rasterized to preserve resolution independence. However, certain kinds of image processing operations, such as CoreImage filters, applied to the layer or its ancestors may force rasterization in a local coordinate space. 

Note:
Shape rasterization may favor speed over accuracy. For example, pixels with multiple intersecting path segments may not give exact results.

以上是官方的描述:
这里是说CAShapeLayer是在其坐标系统内绘制贝塞尔曲线的。因此,使用CAShapeLayer需要与UIBezierPath一起使用。

它有一个path属性,而UIBezierPath就是对CGPathRef类型的封装,因此这两者配合起来使用才可以的哦!

/* The path defining the shape to be rendered. If the path extends
 * outside the layer bounds it will not automatically be clipped to the
 * layer, only if the normal layer masking rules cause that. Upon
 * assignment the path is copied. Defaults to null. Animatable.
 * (Note that although the path property is animatable, no implicit
 * animation will be created when the property is changed.) */

@property(nullable) CGPathRef path;

CAShapeLayer:属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存。

CAShapeLayer就不需要drawRect。

因为需要UIBezierPath,所以我们还需要描述以下UIBezierPath和CAShapeLayer的关系,两者的关系如下:

CAShapeLayer与UIBezierPath的关系:

CAShapeLayer中shape代表形状的意思,所以需要形状才能生效,贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装
    贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape
    用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线

如何画一个圆环:

func drawCircle() -> CAShapeLayer {
        // 创建对象
        let circleLayer = CAShapeLayer()
        // 指定frame,只是为了设置宽度和高度
        circleLayer.frame = CGRectMake(0, 0, 300, 300)
        circleLayer.position = self.view.center
        circleLayer.fillColor = UIColor.clearColor().CGColor
        circleLayer.lineWidth = 2.0
        circleLayer.strokeColor = UIColor.redColor().CGColor

        //使用UIBezierPath创建路径
        let frame = CGRectMake(0, 0, 300, 300)
        let circlePath = UIBezierPath(ovalInRect: frame)

        //设置CAShapLayer与UIBezierPath关联
        circleLayer.path = circlePath.CGPath

        // 将CAShaperLayer放到某个层上显示
        self.view.layer.addSublayer(circleLayer)

        return circleLayer
    }

直接将circleLayer放到self.view.layer上面就可以直接显示出来

以上总结步奏:
1、创建CAShapeLayer对象;
2、配置相关属性;
3、用UIBezierPath创建路径;
4、设置CAShapeLayer与UIBezierPath关联;
5、将layer加载到view.layer上面。

利用CAShapeLayer与UIBezierPath的简单Loading效果:

func drawCircle() -> CAShapeLayer {
        // 创建对象
        let circleLayer = CAShapeLayer()
        // 指定frame,只是为了设置宽度和高度
        circleLayer.frame = CGRectMake(0, 0, 300, 300)
        circleLayer.position = self.view.center
        circleLayer.fillColor = UIColor.clearColor().CGColor
        circleLayer.lineWidth = 2.0
        circleLayer.strokeColor = UIColor.redColor().CGColor

        //使用UIBezierPath创建路径
        let frame = CGRectMake(0, 0, 300, 300)
        let circlePath = UIBezierPath(ovalInRect: frame)

        //设置CAShapLayer与UIBezierPath关联
        circleLayer.path = circlePath.CGPath

        // 将CAShaperLayer放到某个层上显示
        self.view.layer.addSublayer(circleLayer)

        return circleLayer
    }


    func drawHarfCircle() {
        self.loadingLayer = self.drawCircle()
        self.loadingLayer?.strokeStart = 0.0
        self.loadingLayer?.strokeEnd = 0.75
        self.timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: #selector(ViewController.aaa), userInfo: nil, repeats: true)
    }


    func aaa()  {
        if self.loadingLayer?.strokeEnd > 1 && self.loadingLayer?.strokeStart < 1 {
            self.loadingLayer?.strokeStart += 0.1
        } else if self.loadingLayer?.strokeStart == 0 {
            self.loadingLayer?.strokeEnd += 0.1
        }

        if self.loadingLayer?.strokeEnd == 0.0 {
            self.loadingLayer?.strokeStart = 0
        }

        if self.loadingLayer?.strokeStart >= 1 && self.loadingLayer?.strokeEnd >= 1 {
            self.loadingLayer?.strokeStart = 0
            self.timer?.invalidate()
            self
        }
    }

你可能感兴趣的:(CAShapeLay)