Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stroke of CAShapeLayer stops at wrong point?

I drew a simple circular progress view like this:

let trackLayer:CAShapeLayer = CAShapeLayer()
let circularPath:UIBezierPath = UIBezierPath(arcCenter: CGPoint(x: progressView.frame.width / 2, y: 39.5), radius: progressView.layer.frame.size.height * 0.4, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.lightGray.cgColor
trackLayer.lineWidth = 6
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.lineCap = kCALineCapRound
progressView.layer.insertSublayer(trackLayer, at: 0)
let progressLayer:CAShapeLayer = CAShapeLayer()
progressLayer.path = circularPath.cgPath
progressLayer.strokeColor = UIColor.blue.cgColor
progressLayer.lineWidth = 6
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.lineCap = kCALineCapSquare
progressLayer.strokeEnd = 0
progressView.layer.insertSublayer(progressLayer, above: trackLayer)

And on a certain event, I try to update the progressLayer:

if let sublayers = progressView.layer.sublayers {
    (sublayers[1] as! CAShapeLayer).strokeEnd = 0.5
}

Now if I understand strokeEnd correctly, 0 is the start point of the circular path, and 1 is the end point, which means that 0.5 should make it go halfway around, correct? This is what I get instead:

Stroke of progress layer

I tested multiple values and it turns out that around 0.78 makes a full circle. Anything above that, all the way up to 1, doesn't change anything. Can anyone tell me what I'm missing here. Perhaps a problem with the start or end angle of my circular path? Or maybe I just completely misunderstood how strokeEnd works, in which case an explanation would be very much appreciated.

like image 204
Mark Carols Avatar asked Jul 19 '18 18:07

Mark Carols


1 Answers

Can anyone tell me what I'm missing here. Perhaps a problem with the start or end angle of my circular path?

Exactly. Think about your path (circularPath) which is assigned as the path of the shape layer. It goes from startAngle: -CGFloat.pi / 2 to endAngle: 2 * CGFloat.pi. That is more than just a complete circle. Do you see? It's a one-and-a-quarter circle!

That's why, above 0.78 (actually 0.8 or four-fifths), a change in the value of your strokeEnd appears to change nothing; you are just drawing over the start of the circle, redrawing a part of the circle that you already drew.

You probably meant

startAngle: -.pi / 2.0, endAngle: 3 * .pi / 2.0

(although what I would do is go from 0 to .pi*2 and apply a rotation transform so as to start the drawing at the top).


Another problem with your code, which could cause trouble down the line, is that you have forgotten to give either of your layers a frame. Thus they have no size.

like image 151
matt Avatar answered Nov 15 '22 08:11

matt