简介
官方文档对CAShapeLayer的定义如下:
A layer that draws a cubic Bezier spline in its coordinate space.
可以理解为CAShapeLayer是其坐标空间内绘有贝塞尔曲线的图层。
使用CAShapeLayer可以制作蒙板和图层动画,它继承自CALayer,拥有CALayer的全部属性。CAShapeLayer的依赖于贝塞尔曲线UIBezierPath,它决定的ShapeLayer的形状。
StrokeStart和StrokeEnd是ShapeLayer的重要属性,它控制ShapeLayer的cgPath路径的绘制起点和终点,区间都为0~1,0代表从头绘制,1代表绘制到终点。
目录
- ShapeLayer图形动画
 
- ShapeLayer蒙版
 
本文demo的github地址:https://github.com/zephyrw/ShapeLayerDemo.git
使用
ShapeLayer图形动画
动画简介
使用ShapeLayer制作动画原理是通过改变ShapeLayer的strokeEnd属性值来改变ShapeLayer的path的绘制,strokeEnd值区间为0~1
下图为使用ShapeLayer制作仿今日头条下拉动画效果
实现
把整个图形分成三个部分:外边框、左上角的框和所有的横线,分别用贝塞尔曲线绘制这三个部分
外边框
1
   | let draftPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: width, height: height), cornerRadius: 5)
   | 
 
左上角边框
1
   | let squarePath = UIBezierPath(roundedRect: CGRect(x: margin, y: margin, width: smallSquareWH, height: smallSquareWH), cornerRadius: 2)
   | 
 
所有横线
1 2 3 4 5 6 7 8 9
   | 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中
1 2 3 4 5 6 7 8 9 10 11
   | 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和添加到控制器图层
1 2 3 4 5 6 7 8 9
   | 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
1 2 3 4 5 6 7
   | 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方法实现
1 2 3 4 5 6 7 8 9 10 11 12 13
   | @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创建一个带图形的蒙版如下图
<img src=’http://ogdqxib8j.bkt.clouddn.com/MaskImage.png' width=’200’, height=’400’>
思路
新建一个蒙版视图View,然后将绘有贝塞尔曲线的ShapeLayer设置为蒙版视图图层的mask
实现
创建蒙版视图并添加到控制器视图
1 2 3 4
   | let maskView = UIView(frame: view.bounds) maskView.backgroundColor = UIColor.red.withAlphaComponent(0.3) maskView.alpha = 0.8 view.addSubview(maskView)
   | 
 
用贝塞尔曲线绘制蒙版的形状
1 2 3
   | 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
1 2
   | let shapeLayer = CAShapeLayer() shapeLayer.path = bpath.cgPath
   | 
 
将ShapeLayer设为蒙版
1
   | maskView.layer.mask = shapeLayer
   | 
 
接下来就可以运行看效果了
本文demo的github地址:https://github.com/zephyrw/ShapeLayerDemo.git