Frame and Bounds of CAShapeLayer

14,067

Solution 1

When you modify the frame of a CALayer, you are modifying its size and position in the coordinate space of its superlayer. frame is a computed value, based on the object's bounds and position. In this case, the layer does not yet have a superlayer so its coordinate space is dimensionless. When you set the frame, the size gets carried through to the bounds property, but since any point in a dimensionless space is zero, the position will remain zero instead of what you'd intended.

To solve this, you can set the bounds to set the layer's size, and position (which is a real non-computed property) in the coordinate space of the superlayer before adding it as a sublayer.

Solution 2

The following is a quote from the CALayer documentation:

The frame rectangle is position and size of the layer specified in the superlayer’s coordinate space. For layers, the frame rectangle is a computed property that is derived from the values in the bounds, anchorPoint and position properties. When you assign a new value to this property, the layer changes its position and bounds properties to match the rectangle you specified. The values of each coordinate in the rectangle are measured in points.

It looks like with the CAShapeLayer when setting the frame by itself it does't keep the origin values from the assigned CGRect, only the size. When you set the bounds the origin is kept and therefore displays in the proper location. You also need to set the position value to the center point of where you want you shape to be displayed:

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, rect.size.width/2, rect.size.height/2, 100, (0), (M_PI_2), NO);
CGPathAddArc(path, NULL, rect.size.width/2, rect.size.height/2, 100-50, (M_PI_2), (0), YES);
CGPathCloseSubpath(path);
CAShapeLayer* arcLayer = [CAShapeLayer layer];
arcLayer.path = path;
CGRect pathRect = CGPathGetPathBoundingBox(path);
arcLayer.bounds = pathRect;
arcLayer.position = CGPointMake(CGRectGetMidX(pathRect), CGRectGetMidY(pathRect));
[self.layer addSublayer:arcLayer];
Share:
14,067

Related videos on Youtube

h999
Author by

h999

Updated on June 24, 2020

Comments

  • h999
    h999 almost 4 years

    I am working on CAShapeLayer.And trying to draw non-linear path.I want to set frame to CAShapeLayer.So i can use CGPathGetPathBoundingBox method to get frame from CGPathRef.

    Here is code :

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddArc(path, NULL, rect.size.width/2, rect.size.height/2, 100, (0), (M_PI_2), NO);
    CGPathAddArc(path, NULL, rect.size.width/2, rect.size.height/2, 100-50, (M_PI_2), (0), YES);
    CGPathCloseSubpath(path);
    CAShapeLayer* arcLayer = [[CAShapeLayer alloc]init];
    arcLayer.path = path;
    arcLayer.frame = CGPathGetPathBoundingBox(path);
    arcLayer.bounds = CGPathGetPathBoundingBox(path);
    [self.layer addSublayer:arcLayer]; ` 
    

    Please refer my code carefully .I have set same frame and bounds to CAShapeLayer.My problem is if i am not setting bounds (same as frame) ,then it wont show my content or it wont show my content within frame.Why?Please help me.Thanking you.

  • Nico
    Nico over 10 years
    So, in a sentence: Don't set frame, just bounds, and also set position?
  • Brian Shamblen
    Brian Shamblen over 10 years
    Yes. Although, I thought that a 500 point question required a slightly more verbose response.
  • nielsbot
    nielsbot over 10 years
    In general with layers I think you get the best results by setting bounds + position and not frame. But for CAShapeLayer, I don't think bounds is important, unless you want to add a translation to the contents. However this doesn't explain why the path isn't being drawn does it?
  • nielsbot
    nielsbot over 10 years
    I guess the drawing is being done outside the bounds of the enclosing view/layer and one of those has [clips|masks]toBounds = YES.. (just a guess though)
  • Ashish
    Ashish over 10 years
    Thanks with a few change it worked, we almost invested a day in this, thanxx a lot

Related