Search code examples
iosswiftcashapelayer

Unexpected StrokeEnd for CAShapeLayer


I'm drawing a circle using a CAShapeLayer and for some reason, the stroke will only be drawn at 25% intervals. For instance, setting the StrokeEnd to 0.4 draws the stroke to 50% of the circle.

How can I draw the stroke of a CAShapeLayer to the intended position?

import UIKit

class DrawCircle {
    let shapeLayer = CAShapeLayer()
    let trackLayer = CAShapeLayer()
    let center: CGPoint
    let radius: CGFloat
    let startAngle: CGFloat
    let endAngle: CGFloat
    let clockwise: Bool

    let fillColor: CGColor
    let strokeColor: CGColor
    let lineWidth: CGFloat
    var strokeEnd: CGFloat
    let view: UIView
    let circularPath: UIBezierPath
    let withTrack: Bool
    private var trackColor: CGColor

    init(withTrack: Bool, trackColor: CGColor, radius: CGFloat, center: CGPoint, clockwise: Bool, fillColor: CGColor, strokeColor: CGColor, lineWidth: CGFloat, view: UIView) {
        //path params
        self.center = center
        self.radius = radius
        self.startAngle = -CGFloat.pi / 2
        self.endAngle = 2 * CGFloat.pi
        self.clockwise = clockwise
        self.circularPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: clockwise)
        //shape params
        self.fillColor = fillColor
        self.strokeColor = strokeColor
        self.strokeEnd = 0.4
        self.lineWidth = lineWidth

        //view to attach to
        self.view = view
        self.withTrack = withTrack
        if withTrack {
            self.trackColor = trackColor
        } else {
            self.trackColor = UIColor.clear.cgColor
        }
    }

    func draw() {
        if withTrack {
            drawTrack()
            print("track drawn: \(self.trackLayer)")
        }
        shapeLayer.path = circularPath.cgPath
        shapeLayer.strokeColor = strokeColor
        shapeLayer.fillColor = fillColor
        shapeLayer.lineWidth = self.lineWidth
        shapeLayer.strokeEnd = self.strokeEnd
        shapeLayer.lineCap = .round
        view.layer.addSublayer(shapeLayer)
    }

    func drawTrack() {
        trackLayer.path = circularPath.cgPath
        trackLayer.strokeColor = trackColor
        trackLayer.fillColor = UIColor.clear.cgColor
        trackLayer.lineWidth = self.lineWidth
        trackLayer.lineCap = .round
        view.layer.addSublayer(trackLayer)
    }

}

This question was marked as duplicate, however the question is entirely different, and the answer provided draws half a circle, not a complete circle. The ending angle value is entirely different


Solution

  • Change the start and end angles to:

    self.startAngle = -CGFloat.pi / 2 
    self.endAngle = 1.5 * CGFloat.pi