Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // CircularProgressView
- //
- //
- // Created by KuroiDOC on 16/05/19.
- // Copyright © 2019 KuroiDOC. All rights reserved.
- //
- class CircularProgressView : UIView {
- var title : NSAttributedString? {
- didSet { setNeedsLayout() }
- }
- var progress : CGFloat = 0 {
- didSet { setNeedsLayout() }
- }
- var progressTintColor : UIColor = .red {
- didSet { setNeedsLayout() }
- }
- var trackTintColor : UIColor = .gray {
- didSet { setNeedsLayout() }
- }
- var leftText : NSAttributedString? {
- didSet { setNeedsLayout() }
- }
- var rightText : NSAttributedString? {
- didSet { setNeedsLayout() }
- }
- func degsToRads(_ degrees: CGFloat) -> CGFloat {
- return degrees * CGFloat.pi / 180
- }
- override func layoutSubviews() {
- layer.sublayers?.forEach { $0.removeFromSuperlayer() }
- super.layoutSubviews()
- setupLayers()
- }
- private func setupLayers() {
- let rect = self.bounds
- let center = CGPoint(x: rect.origin.x + rect.size.width / 2,
- y: rect.origin.y + rect.size.height / 2)
- let radius = rect.size.height * 0.4
- let trackPath = CGMutablePath()
- trackPath.addArc(center: center, radius: radius, startAngle: degsToRads(130), endAngle: degsToRads(50), clockwise: false)
- let trackLayer = CAShapeLayer()
- trackLayer.name = "Track"
- trackLayer.anchorPoint = .zero
- trackLayer.path = trackPath
- trackLayer.bounds = rect
- trackLayer.lineCap = .round
- trackLayer.strokeColor = trackTintColor.cgColor
- trackLayer.fillColor = backgroundColor?.cgColor
- trackLayer.lineWidth = 10
- trackLayer.allowsGroupOpacity = true
- trackLayer.fillMode = .forwards
- layer.addSublayer(trackLayer)
- let progress = self.progress > 1 ? 1 : self.progress
- let progressPath = CGMutablePath()
- progressPath.addRelativeArc(center: center, radius: radius, startAngle: degsToRads(130), delta: degsToRads(280 * progress), transform: .identity)
- let progressLayer = CAShapeLayer()
- progressLayer.name = "Progress"
- progressLayer.anchorPoint = .zero
- progressLayer.path = progressPath
- progressLayer.bounds = rect
- progressLayer.lineCap = .round
- progressLayer.strokeColor = progressTintColor.cgColor
- progressLayer.fillColor = UIColor.clear.cgColor
- progressLayer.lineWidth = 10
- progressLayer.allowsGroupOpacity = true
- progressLayer.fillMode = .forwards
- progressLayer.strokeEnd = 0
- let strokeEndAnimation = CABasicAnimation()
- strokeEndAnimation.beginTime = self.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.000001
- strokeEndAnimation.duration = 2
- strokeEndAnimation.fillMode = .forwards
- strokeEndAnimation.isRemovedOnCompletion = false
- strokeEndAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
- strokeEndAnimation.keyPath = "strokeEnd"
- strokeEndAnimation.toValue = 1
- strokeEndAnimation.fromValue = 0
- progressLayer.add(strokeEndAnimation, forKey: "strokeEndAnimation")
- layer.addSublayer(progressLayer)
- if let title = title {
- let titleBoundingRect = title.boundingRect(with: CGSize(width: rect.width * 0.4, height: .greatestFiniteMagnitude),
- options: [.usesFontLeading, .usesLineFragmentOrigin],
- context: nil)
- let titleLayer = CATextLayer()
- titleLayer.string = title
- titleLayer.position = rect.center
- titleLayer.bounds = titleBoundingRect
- titleLayer.alignmentMode = .center
- layer.addSublayer(titleLayer)
- }
- if let leftText = self.leftText {
- var leftTextPoint = point(at: radius, angle: degsToRads(130), from: center)
- leftTextPoint.x += 4
- let leftTextLayer = CATextLayer()
- leftTextLayer.string = leftText
- leftTextLayer.position = rect.center
- leftTextLayer.frame = CGRect(origin: leftTextPoint, size: leftText.size())
- leftTextLayer.alignmentMode = .center
- layer.addSublayer(leftTextLayer)
- }
- if let rightText = self.rightText {
- var rightTextPoint = point(at: radius, angle: degsToRads(50), from: center)
- rightTextPoint.x -= rightText.size().width + 4
- let rightTextLayer = CATextLayer()
- rightTextLayer.string = rightText
- rightTextLayer.position = rect.center
- rightTextLayer.frame = CGRect(origin: rightTextPoint, size: rightText.size())
- rightTextLayer.alignmentMode = .center
- layer.addSublayer(rightTextLayer)
- }
- }
- func point(at radius: CGFloat, angle: CGFloat, from: CGPoint) -> CGPoint {
- return CGPoint(x: from.x + radius * cos(angle),
- y: from.y + radius * sin(angle))
- }
- }
- extension CGPoint {
- static func / (left: CGPoint, right: CGFloat) -> CGPoint {
- return CGPoint(x: left.x / right, y: left.y / right)
- }
- }
- extension CGRect {
- var center : CGPoint {
- return CGPoint(x: self.origin.x + self.width / 2, y: self.origin.y + self.height / 2)
- }
- init(center: CGPoint, size: CGSize) {
- let origin = CGPoint(x: center.x - size.width / 2, y: center.y - size.height / 2)
- self.init(origin: origin, size: size)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement