簡介
官方文檔對ShapeLayer的定義如下:
A layer that draws a cubic Bezier spline in its coordinate space.
可以理解為ShapeLayer
是其坐標空間內(nèi)繪有貝塞爾曲線的圖層责掏。
使用ShapeLayer
可以制作蒙板和圖層動畫,由于它繼承自CALayer
,因此擁有CALayer
的全部屬性涡拘。而ShapeLayer
最大的不同在于它依賴于貝塞爾曲線UIBezierPath
,用貝塞爾曲線可以定義ShapeLayer
的形狀据德。
ShapeLayer
還有兩個重要的屬性:StrokeStart
和StrokeEnd
鳄乏,它控制ShapeLayer
的cgPath
路徑的繪制起點和終點跷车,區(qū)間都為0~1,0代表繪制的起始位置橱野,1代表繪制的終點位置朽缴。
下面就分別從圖形動畫和蒙版兩方面來講講ShapeLayer
的使用。
目錄
- ShapeLayer圖形動畫
- ShapeLayer蒙版
本文demo的github地址:<a>https://github.com/zephyrw/ShapeLayerDemo.git</a>
使用
ShapeLayer圖形動畫
動畫簡介
使用ShapeLayer制作動畫原理是通過改變ShapeLayer的strokeEnd屬性值來改變ShapeLayer的path的繪制水援,strokeEnd值區(qū)間為0~1
下圖為使用ShapeLayer制作仿今日頭條下拉動畫效果
實現(xiàn)
把整個圖形分成三個部分:外邊框密强、左上角的框和所有的橫線,分別用貝塞爾曲線繪制這三個部分
外邊框
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方法實現(xiàn)
@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創(chuàng)建一個帶圖形的蒙版如下圖
思路
新建一個蒙版視圖View
,然后將繪有貝塞爾曲線的ShapeLayer
設置為蒙版視圖圖層的mask
實現(xiàn)
創(chuàng)建蒙版視圖并添加到控制器視圖
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)
創(chuàng)建ShapeLayer或渤,設置之前創(chuàng)建的貝塞爾曲線為cgPath
let shapeLayer = CAShapeLayer()
shapeLayer.path = bpath.cgPath
將ShapeLayer設為蒙版
maskView.layer.mask = shapeLayer
接下來就可以運行看效果了。
總結(jié)
ShapeLayer
作為一個帶形狀的圖層许帐,作用不僅限于上面的圖層動畫和蒙版動畫劳坑。它還可以配合核心動畫CAAnimation
做出很多很炫的效果,比如用ShapeLayer
的cgPath
作CABasicAnimation
的keyPath
成畦,通過將fromValue
和toValue
設為不同的形狀路徑距芬,可以完成很自然的形變動畫,大家也可以自己動手實現(xiàn)一下循帐。
本文demo的github地址:<a>https://github.com/zephyrw/ShapeLayerDemo.git</a>