问题描述
我正在尝试制作一个Gauge UIView,以尽可能模仿以下图像
func gradientBezierPath(percent: CGFloat) -> UIBezierPath {
// vary this to move the start of the arc
let startAngle = CGFloat(180).toRadians()//-CGFloat.pi / 2 // This corresponds to 12 0'clock
// vary this to vary the size of the segment,in per cent
let proportion = CGFloat(50 * percent)
let centre = CGPoint (x: self.frame.size.width / 2,y: self.frame.size.height / 2)
let radius = self.frame.size.height/4//self.frame.size.width / (CGFloat(130).toRadians())
let arc = CGFloat.pi * 2 * proportion / 100 // i.e. the proportion of a full circle
// Start a mutable path
let cPath = UIBezierPath()
// Move to the centre
cPath.move(to: centre)
// Draw a line to the circumference
cPath.addLine(to: CGPoint(x: centre.x + radius * cos(startAngle),y: centre.y + radius * sin(startAngle)))
// NOW draw the arc
cPath.addArc(withCenter: centre,radius: radius,startAngle: startAngle,endAngle: arc + startAngle,clockwise: true)
// Line back to the centre,where we started (or the stroke doesn't work,though the fill does)
cPath.addLine(to: CGPoint(x: centre.x,y: centre.y))
return cPath
}
override func draw(_ rect: CGRect) {
// let endAngle = percent == 1.0 ? 0 : (percent * 180) + 180
path = UIBezierPath(arcCenter: CGPoint(x: self.frame.size.width/2,y: self.frame.size.height/2),radius: self.frame.size.height/4,startAngle: CGFloat(180).toRadians(),endAngle: CGFloat(0).toRadians(),clockwise: true)
percentPath = UIBezierPath(arcCenter: CGPoint(x: self.frame.size.width/2,clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = self.path.cgPath
shapeLayer.strokeColor = UIColor(red: 110 / 255,green: 78 / 255,blue: 165 / 255,alpha: 1.0).cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 5.0
shapeLayer.lineCap = .round
self.layer.addSublayer(shapeLayer)
percentLayer.path = self.percentPath.cgPath
percentLayer.strokeColor = UIColor(red: 255 / 255,green: 93 / 255,blue: 41 / 255,alpha: 1.0).cgColor
percentLayer.fillColor = UIColor.clear.cgColor
percentLayer.lineWidth = 8.0
// percentLayer.strokeEnd = CGFloat(percent)
percentLayer.lineCap = .round
self.layer.addSublayer(percentLayer)
// n.b. as @MartinR points out `cPath.close()` does the same!
// circle shape
circleShape.path = gradientBezierPath(percent: 1.0).cgPath//cPath.cgPath
circleShape.strokeColor = UIColor.clear.cgColor
circleShape.fillColor = UIColor.green.cgColor
self.layer.addSublayer(circleShape)
gradient.frame = frame
gradient.mask = circleShape
gradient.type = .radial
gradient.colors = [UIColor(red: 255 / 255,alpha: 0.0).cgColor,UIColor(red: 255 / 255,alpha: 0.4).cgColor]
gradient.locations = [0,0.35,1]
gradient.startPoint = CGPoint(x: 0.49,y: 0.55) // increase Y adds more orange from top to bottom
gradient.endPoint = CGPoint(x: 0.98,y: 1) // increase x pushes orange out more to edges
self.layer.addSublayer(gradient)
//myTextLayer.string = "\(Int(percent * 100))"
myTextLayer.backgroundColor = UIColor.clear.cgColor
myTextLayer.foregroundColor = UIColor.white.cgColor
myTextLayer.fontSize = 85.0
myTextLayer.frame = CGRect(x: (self.frame.size.width / 2) - (self.frame.size.width/8),y: (self.frame.size.height / 2) - self.frame.size.height/8,width: 120,height: 120)
self.layer.addSublayer(myTextLayer)
}
尝试对量规值的变化进行动画处理时出现问题。我可以通过修改percentLayer
来为strokeEnd
制作动画,但是如果量规的百分比值有较大变化,则对circleShape.path
进行渐变动画会导致某些不平滑的动画。这是我用来设置两层动画的函数(现在每2秒在计时器上调用一次,以模拟量规值的变化)。
func randomPercent() {
let random = CGFloat.random(in: 0.0...1.0)
// Animate the percent layer
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = percentLayer.strokeEnd
animation.toValue = random
animation.duration = 1.5
percentLayer.strokeEnd = random
percentLayer.add(animation,forKey: nil)
// Animate the gradient layer
let newShapePath = gradientBezierPath(percent: random)
let gradientAnimation = CABasicAnimation(keyPath: "path")
gradientAnimation.duration = 1.5
gradientAnimation.toValue = newShapePath
gradientAnimation.fromValue = circleShape.path
circleShape.path = newShapePath.cgPath
self.circleShape.add(gradientAnimation,forKey: nil)
myTextLayer.string = "\(Int(random * 100))"
}
请注意,当动画的值进行很小的更改时,动画看起来很好。但是,当变化较大时,渐变动画看起来根本不自然。关于如何改善这一点的任何想法?也许可以设置不同的keyPath动画以获得更好的性能?任何帮助将不胜感激!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)