如何在Swift上使用UIbezierPath进行通用的圆形绘制(使用lineDashPattern)

时间:2017-03-22 15:06:32

标签: ios swift core-graphics uibezierpath cashapelayer

我即将制作通用调谐器应用,但当我尝试绘制模拟仪表时,它会在不同的设备上混乱。也许它非常硬编码。检查一下:

enter image description here

标签也在同一个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)
}

有人可以帮助我在没有硬编码的情况下获得这些值吗?也就是说,我想在故事板中制作薄片/厚片(在iPhone 7上运行)。我想让这个应用程序具有普遍性。

注意:自动调整是正确的,对吗?

提前致谢。

1 个答案:

答案 0 :(得分:1)

@Denis - 是的,我认为您的硬编码值会伤害您,特别是对于lineDashPattern。

试一试。它使用线的长度(弧)和刻度的数量来计算lineDashPattern的“间隙”(可能需要对边界进行一些调整以及什么不是))。

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


}