如何在 Swift 上使用 UIbezierPath 制作通用圆形绘图(使用 lineDashPattern)
How to make universal round draws (with lineDashPattern) with UIbezierPath on Swift
我正准备制作一个通用的调谐器应用程序,但是当我尝试绘制一个模拟仪表时,它在不同的设备上变得一团糟。也许它是非常硬编码的..检查这个:
标签也在同一个UIView下。检查绘制这些路径的代码:
override func draw(_ rect: CGRect) {
let center = CGPoint(x:bounds.width/2, y: bounds.height)
var radius: CGFloat = max(bounds.width, bounds.height+50)
// Define the thickness of the arc.
let arcWidth: CGFloat = 1
let startAngle: CGFloat = π
let endAngle: CGFloat = 2 * π
var path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
path.lineWidth = arcWidth
counterColor.setStroke()
path.stroke()
radius = max(bounds.width, bounds.height+70)
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
let strokeColor = UIColor.black.cgColor
roundThinLayer.path = path.cgPath
roundThinLayer.strokeColor = strokeColor
roundThinLayer.lineWidth = 16.0
roundThinLayer.fillColor = UIColor.clear.cgColor
roundThinLayer.lineDashPattern = [ 0.5, 4.55 ]
//roundThinLayer.lineDashPhase = 0.25
self.layer.addSublayer(roundThinLayer)
radius = max(bounds.width, bounds.height+90)
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
roundThickLayer.path = path.cgPath
roundThickLayer.strokeColor = strokeColor
roundThickLayer.lineWidth = 40
roundThickLayer.fillColor = UIColor.clear.cgColor
roundThickLayer.lineDashPattern = [ 1.5, 140 ]
roundThickLayer.lineDashPhase = 0.25
self.layer.addSublayer(roundThickLayer)
}
有人可以帮助我在不进行硬编码的情况下获得这些值吗?即我想像故事板中那样制作 thins/thicks 破折号(即 iPhone 7 上的 运行)。我想让这个应用程序通用。
注意:自动调整大小正确,对吗?
提前致谢。
@Denis - 是的,我认为您的硬编码值正在伤害您,特别是对于 lineDashPattern。
试一试。它使用线的长度(弧)和刻度数来计算 lineDashPattern 的 "gaps"(可能需要对边界进行一些调整等等)。
public override func draw(_ rect: CGRect) {
let center = CGPoint(x:bounds.width/2, y: bounds.height)
var radius: CGFloat = max(bounds.width, bounds.height+50)
// Define the thickness of the arc.
let arcWidth: CGFloat = 1
let startAngle: CGFloat = CGFloat(M_PI) // π
let endAngle: CGFloat = CGFloat(2 * M_PI) // π
let counterColor = UIColor.red
var path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
path.lineWidth = arcWidth
counterColor.setStroke()
path.stroke()
// init vars for later use
var nTicks = 0
var tickWidth = 0.0
var gapWidth = 0.0
radius += 20
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
let strokeColor = UIColor.black.cgColor
let roundThinLayer = CAShapeLayer()
// number of short ticks to draw
nTicks = 150
// thickness of short ticks
tickWidth = 0.5
// calculate the gap between ticks
gapWidth = ((M_PI * Double(radius) / 2) - (tickWidth * Double(nTicks))) / Double(nTicks - 1)
roundThinLayer.path = path.cgPath
roundThinLayer.strokeColor = strokeColor
roundThinLayer.lineWidth = 20.0
roundThinLayer.fillColor = UIColor.clear.cgColor
roundThinLayer.lineDashPattern = [ tickWidth as NSNumber, gapWidth as NSNumber ]
roundThinLayer.lineDashPhase = CGFloat(tickWidth / Double(2))
self.layer.addSublayer(roundThinLayer)
radius += 20
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
let roundThickLayer = CAShapeLayer()
// number of tall ticks to draw
nTicks = 7
// thickness of tall ticks
tickWidth = 1.5
// calculate the gap between ticks
gapWidth = ((M_PI * Double(radius) / 2) - (tickWidth * Double(nTicks))) / Double(nTicks - 1)
roundThickLayer.path = path.cgPath
roundThickLayer.strokeColor = strokeColor
roundThickLayer.lineWidth = 40
roundThickLayer.fillColor = UIColor.clear.cgColor
roundThickLayer.lineDashPattern = [ tickWidth as NSNumber, gapWidth as NSNumber ]
roundThickLayer.lineDashPhase = CGFloat(tickWidth / Double(2))
self.layer.addSublayer(roundThickLayer)
self.clipsToBounds = true
}
我正准备制作一个通用的调谐器应用程序,但是当我尝试绘制一个模拟仪表时,它在不同的设备上变得一团糟。也许它是非常硬编码的..检查这个:
标签也在同一个UIView下。检查绘制这些路径的代码:
override func draw(_ rect: CGRect) {
let center = CGPoint(x:bounds.width/2, y: bounds.height)
var radius: CGFloat = max(bounds.width, bounds.height+50)
// Define the thickness of the arc.
let arcWidth: CGFloat = 1
let startAngle: CGFloat = π
let endAngle: CGFloat = 2 * π
var path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
path.lineWidth = arcWidth
counterColor.setStroke()
path.stroke()
radius = max(bounds.width, bounds.height+70)
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
let strokeColor = UIColor.black.cgColor
roundThinLayer.path = path.cgPath
roundThinLayer.strokeColor = strokeColor
roundThinLayer.lineWidth = 16.0
roundThinLayer.fillColor = UIColor.clear.cgColor
roundThinLayer.lineDashPattern = [ 0.5, 4.55 ]
//roundThinLayer.lineDashPhase = 0.25
self.layer.addSublayer(roundThinLayer)
radius = max(bounds.width, bounds.height+90)
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
roundThickLayer.path = path.cgPath
roundThickLayer.strokeColor = strokeColor
roundThickLayer.lineWidth = 40
roundThickLayer.fillColor = UIColor.clear.cgColor
roundThickLayer.lineDashPattern = [ 1.5, 140 ]
roundThickLayer.lineDashPhase = 0.25
self.layer.addSublayer(roundThickLayer)
}
有人可以帮助我在不进行硬编码的情况下获得这些值吗?即我想像故事板中那样制作 thins/thicks 破折号(即 iPhone 7 上的 运行)。我想让这个应用程序通用。
注意:自动调整大小正确,对吗?
提前致谢。
@Denis - 是的,我认为您的硬编码值正在伤害您,特别是对于 lineDashPattern。
试一试。它使用线的长度(弧)和刻度数来计算 lineDashPattern 的 "gaps"(可能需要对边界进行一些调整等等)。
public override func draw(_ rect: CGRect) {
let center = CGPoint(x:bounds.width/2, y: bounds.height)
var radius: CGFloat = max(bounds.width, bounds.height+50)
// Define the thickness of the arc.
let arcWidth: CGFloat = 1
let startAngle: CGFloat = CGFloat(M_PI) // π
let endAngle: CGFloat = CGFloat(2 * M_PI) // π
let counterColor = UIColor.red
var path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
path.lineWidth = arcWidth
counterColor.setStroke()
path.stroke()
// init vars for later use
var nTicks = 0
var tickWidth = 0.0
var gapWidth = 0.0
radius += 20
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
let strokeColor = UIColor.black.cgColor
let roundThinLayer = CAShapeLayer()
// number of short ticks to draw
nTicks = 150
// thickness of short ticks
tickWidth = 0.5
// calculate the gap between ticks
gapWidth = ((M_PI * Double(radius) / 2) - (tickWidth * Double(nTicks))) / Double(nTicks - 1)
roundThinLayer.path = path.cgPath
roundThinLayer.strokeColor = strokeColor
roundThinLayer.lineWidth = 20.0
roundThinLayer.fillColor = UIColor.clear.cgColor
roundThinLayer.lineDashPattern = [ tickWidth as NSNumber, gapWidth as NSNumber ]
roundThinLayer.lineDashPhase = CGFloat(tickWidth / Double(2))
self.layer.addSublayer(roundThinLayer)
radius += 20
path = UIBezierPath(arcCenter: center,
radius: radius/2 - arcWidth/2,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
let roundThickLayer = CAShapeLayer()
// number of tall ticks to draw
nTicks = 7
// thickness of tall ticks
tickWidth = 1.5
// calculate the gap between ticks
gapWidth = ((M_PI * Double(radius) / 2) - (tickWidth * Double(nTicks))) / Double(nTicks - 1)
roundThickLayer.path = path.cgPath
roundThickLayer.strokeColor = strokeColor
roundThickLayer.lineWidth = 40
roundThickLayer.fillColor = UIColor.clear.cgColor
roundThickLayer.lineDashPattern = [ tickWidth as NSNumber, gapWidth as NSNumber ]
roundThickLayer.lineDashPhase = CGFloat(tickWidth / Double(2))
self.layer.addSublayer(roundThickLayer)
self.clipsToBounds = true
}