最近公司新项目要用swift做ios,产品图上有个显示体重的圆环。刚学不久实在是不会写。于是找了几个用swift写的仪表盘稍作修改。先来一张效果图:
代码:
import UIKit
extension UIViewController {
var bounds : CGRect {
get {
return view.bounds
}
}
}
extension UIColor {
class func CG_COLOR(颜色数组 values : Array<CGFloat>) -> CGColor {
let r = values[0]
let g = values[1]
let b = values[2]
let a = values[3]
return UIColor.init(red: r, green: g, blue: b, alpha: a).cgColor
}
}
class TestViewController: UIViewController {
var progressLayer : CAShapeLayer?
var progressLayer1 : CAShapeLayer?
//体重
var aLabel : UILabel?
//kg
var kgLabel : UILabel?
//BMI
var BMILabel : UILabel?
var needleLayer : CAShapeLayer?
override func viewDidLoad() {
super.viewDidLoad()
self.drawProgressLayer()
self.drawGradientLayer()
self.drawScale()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//根据半径画圆
func drawCurve(Radius r : CGFloat) -> CAShapeLayer {
let path = UIBezierPath.init(arcCenter: view.center, radius: r, startAngle:-(CGFloat)(M_PI), endAngle:(CGFloat)(M_PI), clockwise: true)
let curve = CAShapeLayer.init()
curve.lineWidth = 2.0
curve.fillColor = UIColor.clear.cgColor
curve.strokeColor = UIColor.white.cgColor
curve.path = path.cgPath
return curve
}
func drawProgressLayer() {
let outArc = self.drawCurve(Radius: 147.5)
let inArc = self.drawCurve(Radius: 82.5)
view.layer.addSublayer(outArc)
view.layer.addSublayer(inArc)
let progressPath = UIBezierPath.init(arcCenter: view.center, radius: 115, startAngle: -(CGFloat)(M_PI), endAngle:0, clockwise: true)
progressLayer = CAShapeLayer()
progressLayer?.lineWidth = 60.0
progressLayer?.fillColor = UIColor.clear.cgColor
progressLayer?.strokeColor = UIColor.red.cgColor
progressLayer?.strokeStart = 0
progressLayer?.strokeEnd = 1
progressLayer?.path = progressPath.cgPath
view.layer.addSublayer(progressLayer!)
let progressPath1 = UIBezierPath.init(arcCenter: view.center, radius: 115, startAngle: 0, endAngle:(CGFloat)(M_PI), clockwise: true)
progressLayer1 = CAShapeLayer()
progressLayer1?.lineWidth = 60.0
progressLayer1?.fillColor = UIColor.clear.cgColor
progressLayer1?.strokeColor = UIColor.red.cgColor
progressLayer1?.strokeStart = 0
progressLayer1?.strokeEnd = 1
progressLayer1?.path = progressPath1.cgPath
view.layer.addSublayer(progressLayer1!)
}
func drawGradientLayer() {
//0~180颜色渐变
let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.bounds
gradientLayer.colors = [UIColor.CG_COLOR(颜色数组: [0, 1.00, 1.00,0.5]),UIColor.CG_COLOR(颜色数组: [0, 210/255, 1.00,1.00]),UIColor.CG_COLOR(颜色数组: [38/255, 232/255, 61/255,1.00]),UIColor.CG_COLOR(颜色数组: [38/255, 232/255, 61/255,1.00])]
gradientLayer.locations = [0,0.25,0.50,0.75,1.0]
gradientLayer.startPoint = CGPoint.init(x: 0, y: 0)
gradientLayer.endPoint = CGPoint.init(x: 1, y: 0)
gradientLayer.mask = progressLayer
view.layer.addSublayer(gradientLayer)
//180~360颜色渐变
let gradientLayer1 = CAGradientLayer()
gradientLayer1.frame = self.bounds
gradientLayer1.colors = [UIColor.CG_COLOR(颜色数组: [38/255, 232/255, 61/255,1.00]),UIColor.CG_COLOR(颜色数组: [38/255, 232/255, 61/255,1.00]),UIColor.CG_COLOR(颜色数组: [1.00, 153/255, 0,1.00]),UIColor.CG_COLOR(颜色数组: [1.00,0,0,1.00])]
gradientLayer1.locations = [0,0.25,0.50,0.75,1.0]
gradientLayer1.startPoint = CGPoint.init(x: 1, y: 0)
gradientLayer1.endPoint = CGPoint.init(x: 0, y: 0)
gradientLayer1.mask = progressLayer1
view.layer.addSublayer(gradientLayer1)
}
//刻度
func drawScale() {
let perAngle : CGFloat = CGFloat(M_PI) / 50
let calWidth : CGFloat = perAngle / 5
for i in 0...100 {
let startAngel = CGFloat(-M_PI) + perAngle*CGFloat(i)
let endAngel = startAngel + calWidth
let tickPath = UIBezierPath.init(arcCenter: view.center, radius: 140, startAngle: startAngel, endAngle: endAngel, clockwise: true)
let perLayer = CAShapeLayer()
if i % 5 == 0 {
//整数刻度颜色
perLayer.strokeColor = UIColor.white.cgColor
perLayer.lineWidth = 10.0
//整数刻度位置
let point = self.calculateTextPosition(center: view.center, angle: -startAngel)
let calibrationLabel = UILabel.init(frame: CGRect.init(x: point.x - 10, y: point.y - 10, width: 30, height: 20))
if(i == 0){
calibrationLabel.text = ""
}else if(i*2 == 200){
calibrationLabel.text = "0/" + String.init(format: "%d", i * 2)
}else{
calibrationLabel.text = String.init(format: "%d", i * 2)
}
calibrationLabel.font = UIFont.systemFont(ofSize: 10)
//整数刻度对应值的颜色
calibrationLabel.textColor = UIColor.white
calibrationLabel.textAlignment = .center
view.addSubview(calibrationLabel)
}
else {
perLayer.strokeColor = UIColor.CG_COLOR(颜色数组: [0.22,0.66,0.87,1.0])
perLayer.lineWidth = 5
}
perLayer.path = tickPath.cgPath
view.layer.addSublayer(perLayer)
}
needleLayer = CAShapeLayer()
needleLayer?.fillColor = UIColor.white.cgColor
needleLayer?.lineWidth = 1.0
//指针颜色
needleLayer?.strokeColor = UIColor.white.cgColor
view.layer.addSublayer(needleLayer!)
self.showDataLabel()
self.drawNeedle(progressValue: 0.0)
}
//指针
func drawNeedle(progressValue value:CGFloat) {
//中心小圆
// let centerCircle = UIBezierPath.init(arcCenter: view.center, radius: 20, startAngle: CGFloat(-M_PI / 16), endAngle: CGFloat(17 / 16 * M_PI), clockwise: false)
// let centerCircleLayer = CAShapeLayer()
// centerCircleLayer.strokeColor = UIColor.red.cgColor
// centerCircleLayer.lineWidth = 3.0
// centerCircleLayer.path = centerCircle.cgPath
// centerCircleLayer.fillColor = UIColor.clear.cgColor
// view.layer.addSublayer(centerCircleLayer)
let angel = CGFloat(M_PI) * (1 - value)
let leewayX : CGFloat = CGFloat(5 * sinf(Float(angel)))
let leewayY : CGFloat = CGFloat(5 * cosf(Float(angel)))
let startPX = CGFloat(82.5 * cosf(Float(angel))) + view.center.x
let startPY = CGFloat(-82.5 * sinf(Float(angel))) + view.center.y
let startPX1 = startPX - leewayX
let startPX2 = startPX + leewayX
let startPY1 = startPY - leewayY
let startPY2 = startPY + leewayY
let endPX = CGFloat(110 * cosf(Float(angel))) + view.center.x
let endPY = CGFloat(-110 * sinf(Float(angel))) + view.center.y
let needlePath = UIBezierPath.init()
needlePath.move(to: CGPoint.init(x: startPX1, y: startPY1))
needlePath.addLine(to: CGPoint.init(x: endPX, y: endPY))
needlePath.addLine(to: CGPoint.init(x: startPX2, y: startPY2))
needleLayer?.path = needlePath.cgPath
}
//计算label位置
func calculateTextPosition(center:CGPoint,angle:CGFloat) -> CGPoint {
let calRadius:Float = 125.0
let x = calRadius * cosf(Float(angle))
let y = calRadius * sinf(Float(angle))
return CGPoint.init(x: CGFloat(x) + center.x, y: -CGFloat(y) + center.y)
}
@IBAction func sliderAction(_ sender: UISlider) {
// progressLayer?.strokeEnd = CGFloat(sender.value/2)
self.drawNeedle(progressValue: CGFloat(sender.value))
self.displayShowLabel(sliderP: CGFloat(sender.value))
}
//数值显示
func showDataLabel() {
aLabel = UILabel.init(frame: CGRect.init(x: 0, y: view.center.y-40 , width: self.bounds.size.width, height: 30))
aLabel?.textColor = UIColor.black
aLabel?.text = "0"
aLabel?.font = UIFont.boldSystemFont(ofSize: 30)
aLabel?.textAlignment = .center
view.addSubview(aLabel!)
kgLabel = UILabel.init(frame: CGRect.init(x: 0, y: view.center.y , width: self.bounds.size.width, height: 20))
kgLabel?.textColor = UIColor.black
kgLabel?.text = "kg"
kgLabel?.font = UIFont.boldSystemFont(ofSize: 15)
kgLabel?.textAlignment = .center
view.addSubview(kgLabel!)
BMILabel = UILabel.init(frame: CGRect.init(x: 0, y: view.center.y+20 , width: self.bounds.size.width, height: 30))
BMILabel?.textColor = UIColor.black
BMILabel?.text = "BMI:"+"0"
BMILabel?.font = UIFont.boldSystemFont(ofSize: 20)
BMILabel?.textAlignment = .center
view.addSubview(BMILabel!)
self.displayShowLabel(sliderP:0.0)
}
func displayShowLabel(sliderP progress:CGFloat) {
//format: "%.2f" 保留两位小数
let numberS : String = String.init(format: "%.1f", progress*100)
aLabel?.text = numberS
}
}