Search code examples
iosswiftuikitcore-graphicsquartz-core

Drown dashed lines on swift getting weird


I'm trying to draw some dashed lines in an UIView but I don't know if I'm doing it right. The first dash has half width compared to the others.

Code:

    let strokeColor                      = UIColor.white.cgColor
    let path = UIBezierPath()
    path2.move(to: CGPoint(x: 0, y: 50)) 
    path2.addLine(to: CGPoint(x: 340, y: 50))

    //thickHorizontalLayer.frame         = frame
    thickHorizontalLayer.path            = path.cgPath
    thickHorizontalLayer.strokeColor     = strokeColor
    thickHorizontalLayer.lineWidth       = 15
    thickHorizontalLayer.fillColor       = UIColor.clear.cgColor
    thickHorizontalLayer.lineDashPattern = [ 0.5, 6 ]
    thickHorizontalLayer.lineDashPhase   = 0.25

    self.layer.addSublayer(thickHorizontalLayer)

Look what it draws: https://i.sstatic.net/7UTdj.jpg

Is this the best way to do it? If you see, the first dash is thiner than others...

plus question: how I can get the y value of the UIView's bound? e.g. bound=340, is this case above.

EDIT:

I'm Trying to draw 2 dash patterns (One thin and other thick) but it's getting confusing...:

    fileprivate let thickHorizontalLayer = CAShapeLayer()
    fileprivate let thinHorizontalLayer = CAShapeLayer()

    let strokeColor                      = UIColor.white.cgColor
    let path2 = UIBezierPath()
    path2.move(to: CGPoint(x: 20, y: 50)) 

    path2.addLine(to: CGPoint(x: 320, y: 50)) 

    //thickHorizontalLayer.frame           = frame
    thickHorizontalLayer.path            = path2.cgPath
    thickHorizontalLayer.strokeColor     = strokeColor
    thickHorizontalLayer.lineWidth       = 20
    thickHorizontalLayer.fillColor       = UIColor.clear.cgColor
    thickHorizontalLayer.lineDashPattern = [ 1, 73.5 ]
    //thickHorizontalLayer.lineDashPhase   = 0.25

    self.layer.addSublayer(thickHorizontalLayer)

    let path3 = UIBezierPath()
    path3.move(to: CGPoint(x: 0, y: 52.5)) 
    path3.addLine(to: CGPoint(x: 340.0, y: 52.5)) 


    //thinHorizontalLayer.frame            = frame
    thinHorizontalLayer.path             = path3.cgPath
    thinHorizontalLayer.strokeColor      = strokeColor
    thinHorizontalLayer.lineWidth        = 15.0
    thinHorizontalLayer.fillColor        = UIColor.clear.cgColor
    thinHorizontalLayer.lineDashPattern  = [ 0.5, 6.25 ]
    //thinHorizontalLayer.lineDashPhase    = 0.25

    self.layer.addSublayer(thinHorizontalLayer)

Its drawing this: https://i.sstatic.net/x0AbL.jpg

If look closely, can be seen that it's getting weird (see the color of the dashes)... : https://i.sstatic.net/1dF0Q.jpg

I'm trying to draw 5 dashes from x:20 to x:320, and between them (but stating at x:0 to x:340) draw 9 thinner dashes. Hope someone help me with this...


Solution

  • I've solved this question with this: How to make universal round draws (with lineDashPattern) with UIbezierPath on Swift

        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
    
    
        }