如果你还没使用过ShapeLayer,一定要看看这篇

简介

官方文档对ShapeLayer的定义如下:

A layer that draws a cubic Bezier spline in its coordinate space.

可以理解为ShapeLayer是其坐标空间内绘有贝塞尔曲线的图层。

使用ShapeLayer可以制作蒙板和图层动画,由于它继承自CALayer,因此拥有CALayer的全部属性。而ShapeLayer最大的不同在于它依赖于贝塞尔曲线UIBezierPath,用贝塞尔曲线可以定义ShapeLayer的形状。

ShapeLayer还有两个重要的属性:StrokeStartStrokeEnd,它控制ShapeLayercgPath路径的绘制起点和终点,区间都为0~1,0代表绘制的起始位置,1代表绘制的终点位置。

下面就分别从图形动画和蒙版两方面来讲讲ShapeLayer的使用。

目录

  • ShapeLayer图形动画
  • ShapeLayer蒙版

本文demo的github地址:https://github.com/zephyrw/ShapeLayerDemo.git

使用

ShapeLayer图形动画

动画简介

使用ShapeLayer制作动画原理是通过改变ShapeLayer的strokeEnd属性值来改变ShapeLayer的path的绘制,strokeEnd值区间为0~1

下图为使用ShapeLayer制作仿今日头条下拉动画效果

shapeLayer动画

实现

把整个图形分成三个部分:外边框、左上角的框和所有的横线,分别用贝塞尔曲线绘制这三个部分

外边框
let draftPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: width, height: height), cornerRadius: 5)
左上角边框
let squarePath = UIBezierPath(roundedRect: CGRect(x: margin, y: margin, width: smallSquareWH, height: smallSquareWH), cornerRadius: 2)
所有横线
let linePath = UIBezierPath()       
for i in 0..<3 {
    linePath.move(to: CGPoint(x: shortLineLeft, y: margin + 2 + space * CGFloat(i)))
    linePath.addLine(to: CGPoint(x: shortLineRight, y: margin + 2 + space * CGFloat(i)))
}
for i in 0..<3 {
    linePath.move(to: CGPoint(x: margin, y: margin * 2 + 2 + smallSquareWH + space * CGFloat(i)))
    linePath.addLine(to: CGPoint(x: longLineRight, y: margin * 2 + 2 + smallSquareWH + space * CGFloat(i)))
}
将所有贝塞尔曲线绘制到ShapeLayer中
self.draftShapeLayer = CAShapeLayer()
self.draftShapeLayer!.frame = CGRect(x: 0, y: 0, width: width, height: height)
setupShapeLayer(shapeLayer: self.draftShapeLayer!, path: draftPath.cgPath)
        
self.squareShapeLayer = CAShapeLayer()
self.squareShapeLayer!.frame = CGRect(x: 0, y: 0, width: smallSquareWH, height: smallSquareWH)
setupShapeLayer(shapeLayer: self.squareShapeLayer!, path: squarePath.cgPath)
        
self.lineShapeLayer = CAShapeLayer()
self.lineShapeLayer!.frame = CGRect(x: 0, y: 0, width: width, height: height)
setupShapeLayer(shapeLayer: self.lineShapeLayer!, path: linePath.cgPath)

这里抽出了辅助方法来设置ShapeLayer和添加到控制器图层

private func setupShapeLayer(shapeLayer : CAShapeLayer, path : CGPath) {
    shapeLayer.path = path
    shapeLayer.strokeColor = UIColor.gray.cgColor
    shapeLayer.fillColor = UIColor.white.cgColor
    shapeLayer.lineWidth = 2
    shapeLayer.strokeStart = 0
    shapeLayer.strokeEnd = 0
    self.containerLayer.addSublayer(shapeLayer)
}
添加SliderView
private func addSlider() {
    let slider = UISlider(frame: CGRect(x: 20, y:   UIScreen.main.bounds.height - 50, width:    UIScreen.main.bounds.width - 40, height: 10))
    slider.minimumValue = 0
    slider.maximumValue = 1
    slider.addTarget(self, action: #selector(sliderValueChanged(sender:)), for: UIControlEvents.valueChanged)
    view.addSubview(slider)
    }
sliderValuerChanged方法实现
@objc private func sliderValueChanged(sender: UISlider) {
    guard let draftShapeLayer = self.draftShapeLayer else { return }
    guard let squareShapeLayer = self.squareShapeLayer else { return }
    guard let lineShapeLayer = self.lineShapeLayer else { return }
    draftShapeLayer.strokeEnd = CGFloat(sender.value)
    squareShapeLayer.strokeEnd = CGFloat(sender.value)
    lineShapeLayer.strokeEnd = CGFloat(sender.value)
}

至此,ShapeLayer图形动画就完成了

ShapeLayer蒙版

用ShapeLayer创建一个带图形的蒙版如下图

如果你还没使用过ShapeLayer,一定要看看这篇_第1张图片

思路

新建一个蒙版视图View,然后将绘有贝塞尔曲线的ShapeLayer设置为蒙版视图图层的mask

实现

创建蒙版视图并添加到控制器视图
let maskView = UIView(frame: view.bounds)
maskView.backgroundColor = UIColor.red.withAlphaComponent(0.3)
maskView.alpha = 0.8
view.addSubview(maskView)
用贝塞尔曲线绘制蒙版的形状
let bpath = UIBezierPath(roundedRect: CGRect(x: 10, y: 10, width: view.bounds.width - 20, height: view.bounds.height - 20), cornerRadius: 15)
let circlePath = UIBezierPath(arcCenter: view.center, radius: 100, startAngle: 0, endAngle: CGFloat(M_PI) * 2, clockwise: false)
bpath.append(circlePath)
创建ShapeLayer,设置之前创建的贝塞尔曲线为cgPath
let shapeLayer = CAShapeLayer()
shapeLayer.path = bpath.cgPath
将ShapeLayer设为蒙版
maskView.layer.mask = shapeLayer

接下来就可以运行看效果了。

总结

ShapeLayer作为一个带形状的图层,作用不仅限于上面的图层动画和蒙版动画。它还可以配合核心动画CAAnimation做出很多很炫的效果,比如用ShapeLayercgPathCABasicAnimationkeyPath,通过将fromValuetoValue设为不同的形状路径,可以完成很自然的形变动画,大家也可以自己动手实现一下。

本文demo的github地址:https://github.com/zephyrw/ShapeLayerDemo.git

你可能感兴趣的:(如果你还没使用过ShapeLayer,一定要看看这篇)