简介
官方文档对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