这篇文章通过使用CAShapeLayer和UIBezierPath来画出一个动态显示剩余流量的小动画。
最终实现的效果如下:
Paste_Image.png
动态效果图:
shapeLayerAni.gif
实际中,能够用CALayer完成的任务是比较少的,如果使用这个基础图层就能实现绝大部分的功能,咱们就没有必要再开启一个CAShapeLayer了嘛。
那CAShapeLayer到底有啥子优点嘛!
属性名 | 作用 |
---|---|
path | 图像的绘制路径,path不支持隐式动画 |
fillColor | 填充path的颜色,或无填充。默认为不透明黑色。 |
fillRule | 填充path的规则。选项是非零和偶奇。默认为非零。 |
lineCap | 线端点类型 |
lineDashPattern | 线性模版 |
lineDashPhase | 线型模版的起点 |
lineJoin | 线连接类型 |
lineWidth | 线宽 |
miterLimit | 最大斜接长度。 |
strokeColor | 描边颜色 |
strokeStart | 描边的起点 |
strokeEnd | 描边的终点 |
能看到这里,说明您已经不是一个没有任何基础的小白了。所以特别基础的属性就没必要解释一遍了。下面只是一个不常用或者立即起来稍微费点劲的属性。
lineDashPattern
: 这是一个NSNumber的数组,索引从1开始记,奇数位数值表示实线长度,偶数位数值表示空白长度。系统会按照数值自动重复设置虚线。miterLimit
:最大斜接长度。斜接长度指的是在两条线交汇处和外交之间的距离。只有lineJoin属性为kCALineJoinMiter时miterLimit才有效。边角的角度越小,斜接长度就会越大。为了避免斜接长度过长,我们可以使用miterLimit属性。如果斜接长度超过miterLimit的值,边角会以lineJoin的“bevel”即kCALineJoinBevel类型来显示strokeStart
& strokeEnd
: 描边的起始点位置。范围为0~1.Paste_Image.png
basicLayer.lineDashPattern = [5,2,10,7]
这句话的意思是说这个虚线由四部分组成:
strokeStart它表示描线开始的地方占总路径的百分比。默认值是0。 strokeEnd表示绘制结束的地方站总路径的百分比。默认值是1,如果小于等于strokeStart 则绘制不出任何内容。
手画一张图,解释一下啥意思:
Paste_Image.png
做好后的效果如下:
Paste_Image.png
fileprivate func hollowLayer(){
// 创建空心的layer
let hollowLayer = CAShapeLayer()
hollowLayer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
view.layer.addSublayer(hollowLayer)
hollowLayer.position = view.center
// 最外面待圆角的方形path
let squarePath = UIBezierPath.init(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100), cornerRadius: 5)
// 中间镂空的圆形path
let hollowPath = UIBezierPath.init(ovalIn: CGRect(x: 10, y: 10, width: 80, height: 80))
squarePath.append(hollowPath)
hollowLayer.path = squarePath.cgPath
hollowLayer.fillColor = UIColor.lightGray.cgColor
// 设置路径的填充模式为两个图形的非交集
hollowLayer.fillRule = kCAFillRuleEvenOdd
// 创建进度layer
let processSectorLayer = CAShapeLayer()
view.layer.addSublayer(processSectorLayer)
processSectorLayer.bounds = CGRect(x: 0, y: 0, width: 70, height: 70)
processSectorLayer.position = view.center
// 进度的path
let processSectorPath = UIBezierPath.init(arcCenter: CGPoint.init(x: 35, y: 35), radius: 17.5, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
processSectorLayer.path = processSectorPath.cgPath
processSectorLayer.lineWidth = 35
// 进度的起点和结束位置,设置进度条修改这个值和结束数值就可以了
processSectorLayer.strokeStart = 0.5
processSectorLayer.strokeEnd = 0.75
processSectorLayer.strokeColor = UIColor.lightGray.cgColor
processSectorLayer.fillColor = UIColor.clear.cgColor
}
有了上面对于CAShapeLayer 的基础训练,绘制一个动态的流量图就不是什么困难的事情了。 实现后的效果如下:
1,创建一个view,用来展示进度圆环。 2,在进度的view上面添加一个layer,用来展示进度圆环底部灰色的圆环。 3,在灰色的圆环上面,添加一个layer,用来显示实际的进度。 4,创建一个定时器,定时器用来更新时时进度。
在文章里面咱们只PO出来一些关键的代码,如果想查看源文件,可以自行下载源码哈。
// 进度条layer
lazy var circleProgressLayer: CAShapeLayer = {
let circleProgressLayer = CAShapeLayer()
let circleBounds = CGRect(x: 0, y: 0, width: 250, height: 250)
circleProgressLayer.bounds = circleBounds
circleProgressLayer.position = CGPoint(x: circleBounds.width / 2, y: circleBounds.height / 2)
let circleProgressPath = UIBezierPath.init(arcCenter: CGPoint(x: circleBounds.width / 2, y: circleBounds.height / 2), radius: circleBounds.height / 2, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
circleProgressLayer.strokeStart = 0
circleProgressLayer.strokeEnd = 1
circleProgressLayer.path = circleProgressPath.cgPath
circleProgressLayer.lineWidth = 10
circleProgressLayer.strokeColor = UIColor.init(colorLiteralRed: 0, green: 151, blue: 255, alpha: 1).cgColor
circleProgressLayer.fillColor = UIColor.clear.cgColor
return circleProgressLayer
}()
//开启定时器
timer = Timer.scheduledTimer(timeInterval: 0.04, target: self, selector: #selector(progressShowNumber), userInfo: nil, repeats: true)
// 定时器调用的方法
@objc private func progressShowNumber(){
if progressValue > expectValue - 1 && progressValue < expectValue {
timer.invalidate()
circleProgressLayer.strokeEnd = expectValue / 100
progressLabel.text = "\(expectValue)%"
return
}
if progressValue > expectValue {
timer.invalidate()
return
}
//更新进度文字和进度条的strokeEnd
circleProgressLayer.strokeEnd = CGFloat(progressValue) / 100
progressLabel.text = "\(progressValue)%"
progressValue += 1
}
这两天人正好在San Francisco,抽空去San Jose苹果的大本营溜达溜达。到时候给大家放照哈。 源代码可以在这里下载。https://git.oschina.net/atypical/multAnimation.git