tip:僅僅是CAShapeLayer,CAGradientLayer的簡單使用案例
先上效果圖:
原理:
實現(xiàn)中用到的兩個Layer屹耐,一個CAGradientLayer用來生成漸變色,兩個CAShapeLayer窍育,一個用來劃線,另一個用來做CAGradientLayer的mask用于顯示出所劃線下面的漸變區(qū)域在辆。動畫规揪,直接通過timer,循環(huán)遞增點來實現(xiàn)乍赫。
具體實現(xiàn):
設(shè)置layer:
這個沒啥可說的瓣蛀,給View的layer添加一個GradientLayer和一個LineLayer,給GradientLayer添加一個mask
畫線:
(1)currentIndex是當前已經(jīng)畫到的點,當畫到currentIndex時雷厂,剛好得到第一個點到currentIndex點的線路徑惋增,這時給lineLayer賦值Path,
(2)繼續(xù)從currentIndex點依次連接currentIndex和第一個點對應(yīng)的X軸點改鲫,然后回到第一個點诈皿。此時Path是一個封閉的圖形林束,這時給MaskLayer賦值。
整個路徑就算畫完了稽亏,繼續(xù)進行下一個點壶冒。循環(huán)就生成動畫。
然后就寫完了截歉,太簡單了胖腾。可能是還有好多事沒做瘪松。比如咸作,一個圖怎么能沒有X、Y坐標的值呢宵睦,圖形的走勢是反的记罚,原因是View的原點在左上,我們常識中的折線圖是左下状飞。但這些都不是我要寫篇文章的要點毫胜,我只是想用用CAShapeLayer和CAGradientLayer。
以下是示例代碼:
import UIKit
class KKLineChart: UIView {
var granLayer = CAGradientLayer()
var maskLayer = CAShapeLayer()
var lineLayer = CAShapeLayer()
var timer: Timer?
var currentIndex: Int = 1
private lazy var dataArray:[CGPoint] = {
var floatArray:[CGPoint] = []
for i in 1...20{
let x: CGFloat = CGFloat(i * 15)
let y: CGFloat = CGFloat(arc4random() % 100) + 20
let point = CGPoint(x: x, y: y)
floatArray.append(point)
}
return floatArray
}()
override func didMoveToSuperview() {
super.didMoveToSuperview()
granLayer.colors = [#colorLiteral(red: 1, green: 0.4664840698, blue: 0.2368942201, alpha: 1).cgColor,#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1).cgColor]
granLayer.startPoint = CGPoint(x: 0.5, y: 0)
granLayer.endPoint = CGPoint(x: 0.5, y: 1)
maskLayer.fillColor = UIColor.black.cgColor
lineLayer.strokeColor = #colorLiteral(red: 1, green: 0.4664840698, blue: 0.2368942201, alpha: 1).cgColor
lineLayer.fillColor = UIColor.clear.cgColor
layer.addSublayer(granLayer)
granLayer.mask = maskLayer
layer.addSublayer(lineLayer)
drawLine()
}
override func layoutSubviews() {
super.layoutSubviews()
granLayer.frame = bounds
maskLayer.frame = granLayer.bounds
lineLayer.frame = bounds
}
private func drawLine(){
currentIndex = 1
timer = Timer.scheduledTimer(withTimeInterval: 0.03, repeats: true, block: { (timer) in
let path = UIBezierPath()
let fistPoint = self.dataArray[0]
let lastPoint = self.dataArray[self.currentIndex]
path.move(to: fistPoint)
for (index,point) in self.dataArray.enumerated(){
if self.currentIndex < index {break}
if index != 0 {
path.addLine(to: point)
}
}
self.lineLayer.path = path.cgPath
let fistX = CGPoint(x: fistPoint.x, y: self.bounds.height)
let lastX = CGPoint(x: lastPoint.x, y: self.bounds.height)
path.addLine(to: lastX)
path.addLine(to: fistX)
path.addLine(to: fistPoint)
self.maskLayer.path = path.cgPath
self.currentIndex += 1
if self.currentIndex == self.dataArray.count{timer.invalidate()}
})
}
}