Search code examples
core-graphicscalayercashapelayer

CAShapeLayer - bounds


do you have to set the bounds of a CAShapeLayer?

I'm creating a shape layer and assigning it a path via a UIBezierPath, the shape is a simple circle of the size of the view.

I'm not setting any position or bounds on the layer, is it wrong?

class View: UIView {
...

var backgroundLayer: CAShapeLayer!

func setup() {
    // call from init
    backgroundLayer = CAShapeLayer()
    backgroundLayer.strokeColor = UIColor.redColor()
    backgroundLayer.lineWidth = 3
    backgroundLayer.fillColor = UIColor.clearColor().CGColor
    layer.addSublayer(backgroundLayer)
    ...
}

override func layoutSubviews() {
    super.layoutSubviews()
    backgroundLayer?.path = circlePath(100)
    ...
}

func circlePath(progress: Int) -> CGPath {
    let path = UIBezierPath()
    let inverseProgress = 1 - CGFloat(progress) / 100
    let endAngleOffset = CGFloat(2 * M_PI) * inverseProgress
    path.addArcWithCenter(localCenter, radius: radius, startAngle: CGFloat(-M_PI), endAngle: CGFloat(M_PI) - endAngleOffset, clockwise: true)
    return path.CGPath
}

...
}

Solution

  • As you've already seen, the layer will display just fine even without setting the bounds. So, you don't "have to" set it, but not having a bounds (or having a bounds that is different than the path's bounding box) can sometimes be confusing when doing layout or transforms.

    When it comes to layout, positioning, and transformation there are a few different coordinates to consider.

    1. The layer is positioned relative to it's parent's coordinate system
    2. The path is positioned relative to the shape layer's coordinate system
    3. Each point in the path is relative to the origin (0,0) of the path.

    The shape layer is transformed relative to its center, and the position of the shape layer is also in the center of its bounds. This means that if the shape layer has no bounds (0×0) size, then any transformation (e.g. rotation) happens around the origin of the path (0,0), as opposed to the center of the path. It also means that when setting the position of the shape layer, one is conceptually positioning the origin of the path, as opposed to the center of the path. However, if the origin of the path happens to be the center of the path's bounding box (for example a circle centered around (0,0)) then this isn't really an issue.

    So, to recap: you don't have to set a bounds, but sometimes (depending on the path) positioning or transformation might be clearer when it's set.