环形倒计时

以前项目中有一个小小的需求,是圆形倒计时view,话不多说请看图

环形倒计时
文章图片
circle.gif ?怎么实现这样的需求了?
?圆形可以通过贝塞尔曲线画出来,倒计时可以通过NSTimer或者CADisplayLink来实现,我选择的是后者,后者的刷新频率是1/60s,和UI的刷新屏幕是一毛一样的,可以避免卡顿的问题。

// 默认init方法起始点在CGFloat.pi * (-0.5)圆的最上方 //drawView = MZDrawView(frame: CGRect(x: 100, y: 100, width: 100, height: 200)) // 当然也可以设置圆的起始点 drawView = MZDrawView(frame: CGRect(x: 100, y: 100, width: 100, height: 100), angle: CGFloat.pi * (0.5)) drawView?.backPathColor = UIColor.red drawView?.cycleColor = UIColor.cyan // 倒计时时间 drawView?.duration = 10 // 半径 (不设置的话就默认为MZDrawView的最大内切圆的半径) drawView?.radius = 20 self.view.addSubview(drawView!)

  • 初始化DrawView,可以指定起始点
// MARK: init funcconvenience init(frame: CGRect ,angle:CGFloat) { self.init(frame: frame) self.angle = angle }override init(frame: CGRect) { super.init(frame: frame) self.addSubview(self.timerLabel) let width = self.frame.size.width - lineWidth * 2 - Margin * 2 let height = self.frame.size.height - lineWidth * 2 - Margin * 2 self.timerLabel.frame = CGRect(x: (self.frame.size.height - height)* 0.5, y: (self.frame.size.width - width)* 0.5, width: width, height: height) self.timerLabel.textColor = textColor ?? UIColor.white}

  • drawView的基本属性可以设置倒计时view的样式
/// 圆圈的宽度 var lineWidth: CGFloat = 5.0 private var displayLink: CADisplayLink? var backPathColor: UIColor = UIColor.clear /// 圆圈颜色 var cycleColor: UIColor? /// 倒计时时间label的文字颜色 var textColor: UIColor? { didSet { self.timerLabel.textColor = textColor ?? UIColor.white } } // 默认起始和结束都在圆的顶点 var angle: CGFloat = CGFloat.pi * (-0.5) /// 自定义半径 var radius: CGFloat = 0.0 /// 自定义圆的中心点 var cycleCenter: CGPoint = CGPoint.zero // 倒计时时间 var duration: Double = 0.0 { didSet { if duration < 0.0 { return } // 先停掉link invalidateLink() // 在开启link self.displayLink = CADisplayLink(target: self, selector: #selector(countDown)) self.displayLink?.add(to: RunLoop.current, forMode: .commonModes)} } // 当前进度 var progress: Double = 1.0 { didSet { if progress < 0 || progress > 1 { return } // ceil(返回不小于x的最小整数值) self.timerLabel.text = "\(ceil(self.progress * duration))" self.setNeedsDisplay() } }

  • invalid计时器方法
    【环形倒计时】?当计时器还在work的时候,如果不需要使用了一定要停掉计时器
    ?当计时器还在work的时候,如果不需要使用了一定要停掉计时器
    ?当计时器还在work的时候,如果不需要使用了一定要停掉计时器
/// 在不用的时候要call一下 停掉link // 比如 vc的deinit方法里 open func invalidateLink() { guard let displayLink = self.displayLink else { return } displayLink.isPaused = true displayLink.invalidate() }

  • 根据时间计算比例然后画圆
/// 倒计时 1/60s调用一次 @objc private func countDown() { if progress < 0.0 || progress > 1.0 { invalidateLink() self.progress = 0.0 return } self.progress -= Double((1/60) / self.duration) }

详情请见demo

    推荐阅读