Search code examples
iosswiftuibezierpath

How to align UIBezierPath circle dashes


I am trying to draw a compass using UIBezierPath and adding dashes to the line to mark North, South, East, West directions and points in between. The dashes seem offset (they're not aligned), particularly in the North and South directions and the way I am doing it seems to add an extra dash when the path is closing.

let windCircleOrigin = CGPoint(x: self.center.x * 1.3, y: self.bounds.height / 2.0 - 10)
let windCircleRadius = CGFloat(self.bounds.height * 0.3)
let windCirclePath: UIBezierPath = UIBezierPath(arcCenter: windCircleOrigin, radius: windCircleRadius,startAngle: 0,  endAngle: CGFloat(M_PI) * 2.0, clockwise: true)
        windCirclePath.lineWidth = 6
let dashes: [CGFloat] = [windCirclePath.lineWidth * 0, windCirclePath.lineWidth * 3 ]
        windCirclePath.setLineDash(dashes, count: dashes.count
            , phase: 0.0)
UIColor.whiteColor().setFill()
UIColor.whiteColor().setStroke()
windCirclePath.stroke()
textView(self.windSpeedLabel! + " mph", x: windCircleOrigin.x - 20.0, y: windCircleOrigin.y - 8.0, color: UIColor.whiteColor(), width: 50.0, height: 20.0)
textView("N", x: windCircleOrigin.x - 7.0, y: windCircleOrigin.y - 70.0, color: UIColor.whiteColor(), width: 20, height: 20)
textView("S", x: windCircleOrigin.x - 7.0, y: windCircleOrigin.y + 50.0, color: UIColor.whiteColor(), width: 20, height: 20)
textView("W", x: windCircleOrigin.x - 70.0, y: windCircleOrigin.y - 8.0, color: UIColor.whiteColor(), width: 20, height: 20)
textView("E", x: windCircleOrigin.x + 60.0, y: windCircleOrigin.y - 8.0, color: UIColor.whiteColor(), width: 20, height: 20)

func textView(text: String, x: CGFloat, y: CGFloat, color: UIColor, width: CGFloat, height: CGFloat) {
    let textView = UILabel(frame: CGRectMake(x, y, width, height))
    textView.textAlignment = NSTextAlignment.Left
    textView.textColor = color
    textView.backgroundColor = UIColor.clearColor()
    textView.font = UIFont(name: "HelveticaNeue-Light", size: 12.0)
    textView.text = text
    self.addSubview(textView)
}

enter image description here

Without Dashes


Solution

  • Instead, I would recommend drawing each tick individually. Then you can easily control their location.

    Something like this:

    let path = UIBezierPath()
    let innerRadius: CGFloat = 50
    let outerRadius: CGFloat = 60
    let numTicks = 24
    
    for i in 0..<numTicks {
        let angle = CGFloat(i) * CGFloat(2*M_PI) / CGFloat(numTicks)
        let inner = CGPoint(x: innerRadius * cos(angle), y: innerRadius * sin(angle))
        let outer = CGPoint(x: outerRadius * cos(angle), y: outerRadius * sin(angle))
        path.moveToPoint(inner)
        path.addLineToPoint(outer)
    }
    

    Then you can stroke this path with whatever lineWidth (and lineCapStyle) you want.