Advertisement
Guest User

Untitled

a guest
May 26th, 2019
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.55 KB | None | 0 0
  1. //
  2. // CircularProgressView
  3. //
  4. //
  5. // Created by KuroiDOC on 16/05/19.
  6. // Copyright © 2019 KuroiDOC. All rights reserved.
  7. //
  8.  
  9. class CircularProgressView : UIView {
  10. var title : NSAttributedString? {
  11. didSet { setNeedsLayout() }
  12. }
  13.  
  14. var progress : CGFloat = 0 {
  15. didSet { setNeedsLayout() }
  16. }
  17.  
  18. var progressTintColor : UIColor = .red {
  19. didSet { setNeedsLayout() }
  20. }
  21.  
  22. var trackTintColor : UIColor = .gray {
  23. didSet { setNeedsLayout() }
  24. }
  25.  
  26. var leftText : NSAttributedString? {
  27. didSet { setNeedsLayout() }
  28. }
  29.  
  30. var rightText : NSAttributedString? {
  31. didSet { setNeedsLayout() }
  32. }
  33.  
  34. func degsToRads(_ degrees: CGFloat) -> CGFloat {
  35. return degrees * CGFloat.pi / 180
  36. }
  37.  
  38. override func layoutSubviews() {
  39. layer.sublayers?.forEach { $0.removeFromSuperlayer() }
  40. super.layoutSubviews()
  41. setupLayers()
  42. }
  43.  
  44. private func setupLayers() {
  45. let rect = self.bounds
  46. let center = CGPoint(x: rect.origin.x + rect.size.width / 2,
  47. y: rect.origin.y + rect.size.height / 2)
  48. let radius = rect.size.height * 0.4
  49. let trackPath = CGMutablePath()
  50. trackPath.addArc(center: center, radius: radius, startAngle: degsToRads(130), endAngle: degsToRads(50), clockwise: false)
  51.  
  52. let trackLayer = CAShapeLayer()
  53. trackLayer.name = "Track"
  54. trackLayer.anchorPoint = .zero
  55. trackLayer.path = trackPath
  56. trackLayer.bounds = rect
  57. trackLayer.lineCap = .round
  58. trackLayer.strokeColor = trackTintColor.cgColor
  59. trackLayer.fillColor = backgroundColor?.cgColor
  60. trackLayer.lineWidth = 10
  61. trackLayer.allowsGroupOpacity = true
  62. trackLayer.fillMode = .forwards
  63. layer.addSublayer(trackLayer)
  64.  
  65. let progress = self.progress > 1 ? 1 : self.progress
  66. let progressPath = CGMutablePath()
  67. progressPath.addRelativeArc(center: center, radius: radius, startAngle: degsToRads(130), delta: degsToRads(280 * progress), transform: .identity)
  68.  
  69. let progressLayer = CAShapeLayer()
  70. progressLayer.name = "Progress"
  71. progressLayer.anchorPoint = .zero
  72. progressLayer.path = progressPath
  73. progressLayer.bounds = rect
  74. progressLayer.lineCap = .round
  75. progressLayer.strokeColor = progressTintColor.cgColor
  76. progressLayer.fillColor = UIColor.clear.cgColor
  77. progressLayer.lineWidth = 10
  78. progressLayer.allowsGroupOpacity = true
  79. progressLayer.fillMode = .forwards
  80. progressLayer.strokeEnd = 0
  81.  
  82. let strokeEndAnimation = CABasicAnimation()
  83. strokeEndAnimation.beginTime = self.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.000001
  84. strokeEndAnimation.duration = 2
  85. strokeEndAnimation.fillMode = .forwards
  86. strokeEndAnimation.isRemovedOnCompletion = false
  87. strokeEndAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
  88. strokeEndAnimation.keyPath = "strokeEnd"
  89. strokeEndAnimation.toValue = 1
  90. strokeEndAnimation.fromValue = 0
  91.  
  92. progressLayer.add(strokeEndAnimation, forKey: "strokeEndAnimation")
  93. layer.addSublayer(progressLayer)
  94.  
  95. if let title = title {
  96. let titleBoundingRect = title.boundingRect(with: CGSize(width: rect.width * 0.4, height: .greatestFiniteMagnitude),
  97. options: [.usesFontLeading, .usesLineFragmentOrigin],
  98. context: nil)
  99. let titleLayer = CATextLayer()
  100. titleLayer.string = title
  101. titleLayer.position = rect.center
  102. titleLayer.bounds = titleBoundingRect
  103. titleLayer.alignmentMode = .center
  104. layer.addSublayer(titleLayer)
  105. }
  106.  
  107. if let leftText = self.leftText {
  108. var leftTextPoint = point(at: radius, angle: degsToRads(130), from: center)
  109. leftTextPoint.x += 4
  110. let leftTextLayer = CATextLayer()
  111. leftTextLayer.string = leftText
  112. leftTextLayer.position = rect.center
  113. leftTextLayer.frame = CGRect(origin: leftTextPoint, size: leftText.size())
  114. leftTextLayer.alignmentMode = .center
  115. layer.addSublayer(leftTextLayer)
  116. }
  117.  
  118. if let rightText = self.rightText {
  119. var rightTextPoint = point(at: radius, angle: degsToRads(50), from: center)
  120. rightTextPoint.x -= rightText.size().width + 4
  121. let rightTextLayer = CATextLayer()
  122. rightTextLayer.string = rightText
  123. rightTextLayer.position = rect.center
  124. rightTextLayer.frame = CGRect(origin: rightTextPoint, size: rightText.size())
  125. rightTextLayer.alignmentMode = .center
  126. layer.addSublayer(rightTextLayer)
  127. }
  128. }
  129.  
  130. func point(at radius: CGFloat, angle: CGFloat, from: CGPoint) -> CGPoint {
  131. return CGPoint(x: from.x + radius * cos(angle),
  132. y: from.y + radius * sin(angle))
  133. }
  134. }
  135.  
  136. extension CGPoint {
  137. static func / (left: CGPoint, right: CGFloat) -> CGPoint {
  138. return CGPoint(x: left.x / right, y: left.y / right)
  139. }
  140. }
  141.  
  142. extension CGRect {
  143. var center : CGPoint {
  144. return CGPoint(x: self.origin.x + self.width / 2, y: self.origin.y + self.height / 2)
  145. }
  146.  
  147. init(center: CGPoint, size: CGSize) {
  148. let origin = CGPoint(x: center.x - size.width / 2, y: center.y - size.height / 2)
  149. self.init(origin: origin, size: size)
  150. }
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement