SBTDashboardView.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //
  2. // SBTDashboardView.swift
  3. // SolarBT
  4. //
  5. // Created by weclouds on 2019/3/29.
  6. // Copyright © 2019 weclouds. All rights reserved.
  7. //
  8. import UIKit
  9. class SBTDashboardView: UIView {
  10. var circle000: CAShapeLayer!
  11. //刻度数目
  12. var scaleNumber : Int?
  13. //开始弧度
  14. var start : CGFloat?
  15. //结束弧度
  16. var end : CGFloat?
  17. var pointView:UIView?// 指针
  18. var angle:CGFloat?
  19. var perAngle:CGFloat?
  20. var backAnge:CGFloat?
  21. var space: CGFloat?
  22. var radius1 :CGFloat?
  23. var radius2 :CGFloat?
  24. var radius3 :CGFloat?
  25. var radius4 :CGFloat?
  26. var number : Int?
  27. var powerValue : CGFloat?{
  28. didSet{
  29. if let powerValue = self.powerValue {
  30. circle000.strokeEnd = powerValue
  31. let ang = angle! * powerValue - angle! / 2
  32. UIView.animate(withDuration: 0) {
  33. self.circle000.strokeEnd = powerValue
  34. let value = powerValue * 84
  35. // if value.isNaN == false{// 空值
  36. self.update(Int(value))
  37. // }else{
  38. // self.update(0)
  39. // }
  40. self.pointView?.transform = CGAffineTransform(rotationAngle: ang )
  41. // self.pointView?.transform = CGAffineTransform.identity.
  42. }
  43. backAnge = ang
  44. }
  45. }
  46. }
  47. var solarPowerValue: String?{
  48. didSet{
  49. let str = solarPowerValue! + "W"
  50. let attrStr = NSMutableAttributedString(string: str)
  51. attrStr.addAttributes([NSAttributedString.Key.font:UIFont(name: PingFangSC_Semibold, size: 22) as Any], range: NSRange(location: 0, length: str.count - 1))
  52. attrStr.addAttributes([NSAttributedString.Key.font:UIFont(name: PingFangSC_Semibold, size: 9) as Any], range: NSRange(location: str.count - 1, length: 1))
  53. valueLabel.attributedText = attrStr
  54. }
  55. }
  56. var scaleLayer : [CAShapeLayer]?
  57. lazy var valueLabel: UILabel = {
  58. let valueLabel = UILabel()
  59. valueLabel.textAlignment = .center
  60. valueLabel.textColor = UIColor(hexString: "3B3B3B")
  61. return valueLabel
  62. }()
  63. lazy var powerLabel1: UILabel = {
  64. let powerLabel1 = UILabel()
  65. powerLabel1.text = "Solar_panel_power".da_localizedStr()
  66. powerLabel1.textAlignment = .center
  67. powerLabel1.font = UIFont(name: PingFangSC_Medium, size: 8)
  68. powerLabel1.textColor = UIColor(hexString: "A5A5A5")
  69. return powerLabel1
  70. }()
  71. lazy var statusView : UIImageView = {
  72. let statusView = UIImageView(image: UIImage(named: "power_status"))
  73. return statusView
  74. }()
  75. lazy var statusLabel: UILabel = {
  76. let label = UILabel()
  77. label.font = UIFont(name: PingFangSC_Medium, size: 8)
  78. label.textColor = UIColor(hexString: "#A5A5A5")
  79. label.text = "Normal".da_localizedStr()
  80. return label
  81. }()
  82. override init(frame: CGRect) {
  83. super.init(frame: frame)
  84. // self.backgroundColor = UIColor.cyan
  85. space = 30
  86. radius1 = (self.frame.size.width - space! * 2 ) / 2 - 5
  87. radius2 = radius1! - 10
  88. radius3 = radius2! - radius1! / 2
  89. radius4 = 5
  90. number = 84
  91. start = .pi * 2 / 3
  92. end = .pi / 3
  93. //计算总弧度
  94. angle = 2 * .pi * 5 / 6
  95. perAngle = angle! / (CGFloat(number!) - 1)
  96. scaleLayer = [CAShapeLayer]()
  97. createUI()
  98. }
  99. required init?(coder aDecoder: NSCoder) {
  100. fatalError("init(coder:) has not been implemented")
  101. }
  102. func update(_ value: Int) {
  103. for layer in scaleLayer! {
  104. layer.removeFromSuperlayer()
  105. }
  106. drawScale(number: value)
  107. }
  108. func createUI() {
  109. // addSubview(statusView)
  110. // statusView.addSubview(statusLabel)
  111. drawCircle()
  112. drawCircle2()
  113. drawCircle3()
  114. drawPointer()
  115. renderCircle()
  116. addSubview(valueLabel)
  117. addSubview(powerLabel1)
  118. valueLabel.snp.makeConstraints { (make) in
  119. make.centerX.equalToSuperview()
  120. make.top.equalToSuperview().offset(75)
  121. make.height.equalTo(22)
  122. }
  123. powerLabel1.snp.makeConstraints { (make) in
  124. make.centerX.equalToSuperview()
  125. make.top.equalTo(valueLabel.snp.bottom).offset(0)
  126. make.height.equalTo(11)
  127. }
  128. // statusView.snp.makeConstraints { (make) in
  129. // make.centerX.equalToSuperview()
  130. // make.top.equalTo(powerLabel1.snp.bottom).offset(8)
  131. // make.width.equalTo(60)
  132. // make.height.equalTo(30)
  133. // }
  134. //
  135. // statusLabel.snp.makeConstraints { (make) in
  136. // make.centerX.equalToSuperview()
  137. // make.bottom.equalToSuperview().offset(-5)
  138. // }
  139. }
  140. func drawPointer() {
  141. pointView = UIView(frame: CGRect(x: self.center.x - radius4! / 4, y: self.centerY - radius1! , width: radius4! / 2, height: radius1! ))
  142. pointView?.backgroundColor = UIColor(hexString: "#FD8C23")
  143. addSubview(pointView!)
  144. let path1 = UIBezierPath()
  145. path1 .move(to: CGPoint(x: 0, y: 0))
  146. path1.addLine(to: CGPoint(x: (pointView?.frame.size.width)!, y: 0))
  147. path1.addLine(to: CGPoint(x: (pointView?.frame.size.width)! / 2, y: (pointView?.frame.size.height)! - 30 ))
  148. path1.close()
  149. let layer1 = CAShapeLayer()
  150. layer1.frame = pointView!.bounds
  151. layer1.path = path1.cgPath
  152. layer1.lineJoin = .round
  153. layer1.lineCap = .round
  154. pointView?.layer.mask = layer1
  155. let oldFrame = pointView?.frame
  156. pointView?.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
  157. pointView?.frame = oldFrame!
  158. pointView?.transform = CGAffineTransform(rotationAngle: -angle! / 2)
  159. }
  160. //绘制外围圆环
  161. func drawCircle() {
  162. let layer2 = CAShapeLayer()
  163. layer2.lineWidth = 30
  164. layer2.frame = self.bounds
  165. // 圆环的颜色
  166. layer2.strokeColor = UIColor(hexString: "#F8F8F8")?.cgColor
  167. layer2.fillColor = UIColor.clear.cgColor
  168. //设置半径为视图的半径
  169. let radius : CGFloat = 188 / 2 - 13
  170. //初始化一个路径
  171. let path2 = UIBezierPath(arcCenter: self.center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true) // 是否是逆时针
  172. layer2.path = path2.cgPath
  173. self.layer.addSublayer(layer2)
  174. }
  175. //绘制外围圆环
  176. func drawCircle2() {
  177. let layer3 = CAShapeLayer()
  178. layer3.lineWidth = 1
  179. layer3.frame = self.bounds
  180. // 圆环的颜色
  181. layer3.strokeColor = UIColor(hexString: "#D8D8D8")?.cgColor
  182. layer3.fillColor = UIColor.clear.cgColor
  183. //设置半径为视图的半径
  184. let radius : CGFloat = 188 / 2
  185. //初始化一个路径
  186. let path3 = UIBezierPath(arcCenter: self.center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true) // 是否是逆时针
  187. layer3.path = path3.cgPath
  188. self.layer.addSublayer(layer3)
  189. }
  190. //绘制外围圆环
  191. func drawCircle3() {
  192. let layer4 = CAShapeLayer()
  193. layer4.lineWidth = 1
  194. layer4.frame = self.bounds
  195. // 圆环的颜色
  196. layer4.strokeColor = UIColor(hexString: "#D8D8D8")?.cgColor
  197. layer4.fillColor = UIColor.clear.cgColor
  198. //设置半径为视图的半径
  199. let radius : CGFloat = 188 / 2 - 26
  200. //初始化一个路径
  201. let path4 = UIBezierPath(arcCenter: self.center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true) // 是否是逆时针
  202. layer4.path = path4.cgPath
  203. self.layer.addSublayer(layer4)
  204. }
  205. //进度圆环
  206. func renderCircle() {
  207. let startAngle: CGFloat = start!
  208. let endAngle: CGFloat = end!
  209. let centerX = 188 / 2
  210. let centerY = 188 / 2
  211. let center = CGPoint(x: centerX,y: centerY)
  212. let lineWidth: CGFloat = 3.0
  213. let radius = 188 / 2 - 26
  214. circle000 = CAShapeLayer()
  215. //绘制圆
  216. let circlePath = UIBezierPath.init(arcCenter: center, radius: CGFloat(radius), startAngle: startAngle, endAngle: endAngle, clockwise: true)
  217. circle000.path = circlePath.cgPath
  218. //中间透明
  219. circle000.fillColor = UIColor.clear.cgColor
  220. //临时颜色,下面会用到渐变色来渲染圆环颜色
  221. circle000.strokeColor = UIColor.green.cgColor
  222. //设置线宽
  223. circle000.lineWidth = lineWidth
  224. //设置圆环头部样式
  225. circle000.lineCap = CAShapeLayerLineCap.round
  226. //把自己定义的circle 添加到 背景圆环的layer上
  227. self.layer.addSublayer(circle000)
  228. //下面重点来了:
  229. //1. 之所以能实现圆环的渐变色,并不是我们可以直接在layer上添加一个圆环形状的渐变色,而是
  230. //创建一个通用的正方形渐变色区域,用我们的circle 作为这个渐变区域的mask来截取一个圆环形状的渐变色
  231. //区域。
  232. //2. 为了制造圆环的渐变色效果,只创建一块渐变区域,那是不够的,因为那样画出来的圆左右方向的圆弧颜色
  233. //是对称的,那样就太丑了,不符合整体渐变的要求。所以,我把这个正方形渐变区域垂直切分成两块渐变区域,
  234. //左右区域的颜色顺序相反,起始和结束位置也相反,就出来圆环渐变的效果了。
  235. let gradientLayer = CALayer()
  236. //创建第一个gradientLayer
  237. let colors1 = [
  238. UIColor.RGBA(red: 255, green: 122, blue: 0, alpha: 1.0).cgColor,
  239. UIColor.RGBA(red: 248, green: 248, blue: 248, alpha: 1.0).cgColor
  240. // UIColor.RGBA(red: 255, green: 122, blue: 0, alpha: 1.0).cgColor
  241. ]
  242. let frame1 = CGRect(x: 0, y: 0, width: self.width, height: self.height )
  243. let gradientLayer1 = CAGradientLayer()
  244. gradientLayer1.startPoint = CGPoint(x: 0.5,y: 0)
  245. gradientLayer1.endPoint = CGPoint(x: 0.5,y: 1)
  246. gradientLayer1.frame = frame1
  247. gradientLayer1.colors = colors1
  248. //用一个gradientLayer来承接这两个渐变区域
  249. gradientLayer.addSublayer(gradientLayer1)
  250. //用circle的path形状来截取渐变区域
  251. gradientLayer.mask = circle000
  252. self.layer.addSublayer(gradientLayer)
  253. }
  254. //绘制刻度盘
  255. func drawScale(number scaleN: Int ) {
  256. let color = UIColor(hexString: "#FF7A00")
  257. let color2 = UIColor(hexString: "#D8D8D8")
  258. // let scaleA = scaleN / 100 * number!
  259. // let color = UIColor.red
  260. // let color2 = UIColor.yellow
  261. log.debug("刻度数 - \(scaleN)")
  262. for i in 0..<number! {
  263. let startAngel = start! + perAngle! * CGFloat(i)
  264. let endAngel = startAngel + perAngle! / 5 //刻度线的宽度
  265. // log.debug("开始--\(startAngel) 结束 -- \(endAngel)")
  266. let radius : CGFloat = 188 / 2 - 13
  267. let viewCenter = CGPoint(x: 188 / 2, y: 188 / 2)
  268. let path5 = UIBezierPath(arcCenter: viewCenter, radius: radius, startAngle: startAngel, endAngle: endAngel, clockwise: true)
  269. let layer5 = CAShapeLayer()
  270. if i < (scaleN ) {
  271. layer5 .strokeColor = color?.cgColor
  272. }else{
  273. layer5.strokeColor = color2?.cgColor
  274. }
  275. layer5.lineWidth = 10
  276. layer5.lineJoin = .round
  277. layer5.path = path5.cgPath
  278. self.layer.addSublayer(layer5)
  279. scaleLayer?.append(layer5)
  280. }
  281. }
  282. }
  283. extension UIColor {
  284. class func RGBA(red:CGFloat,green:CGFloat,blue:CGFloat,alpha:CGFloat) -> UIColor{
  285. return UIColor(red: red/255, green: green/255, blue: blue/255, alpha: alpha)
  286. }
  287. }