Can someone explain the CALayer contentsRect property's coordinate system to me?
Asked Answered
S

2

6

I realize that the contentsRect property of CALayer (documentation here) allows one to define how much of the layer to use for drawing, but I do not understand how the coordinate system works, I think.

It seems that when the width/height are smaller, the area used for content is bigger and vice versa. Similarly, negative x,y positions seem to move the content area down and to the right which is the opposite of my intuition.

Can someone explain why this is? I'm sure there is a good reason, but I assume I'm missing some graphics programming background.

Seamaid answered 12/4, 2012 at 5:15 Comment(0)
R
20

the contentsRect property of CALayer (documentation here) allows one to define how much of the layer to use for drawing

No, you're thinking about it incorrectly.

The contentsRect specifies which part of the contents image will be displayed in the layer.

That part is then arranged in the layer according to the contentsGravity property.

If this is kCAGravityResize, the default, this will cause the part to be resized to fit the layer. That would explain the counterintuitive behavior you're seeing -- you make contentsRect smaller, but the layer appears to be the same size, and it appears to "zoom in" on the selected part of the image. You might find it easier to understand if you set contentsGravity to kCAGravityCenter, which won't resize.

Most of the time, you would set the contentsRect to some sub-rect of the identity rect { {0, 0}, {1, 1} }, so you choose to see only part of the contents.

(Think of these as percentages if you like -- if contentsRect has a size of {0.5, 0.5}, you're choosing 50% of the contents.)

If part of the contentsRect goes outside the identity rect, then CA will extend the edge pixels of the contents outwards. This is handy in some cases, but it's not something you'd use on its own -- you'd use it in combination with a mask or with some other layers to achieve some effect.

Rootlet answered 12/4, 2012 at 5:37 Comment(5)
Great answer. That makes more sense. Do you know if there's any official documentation that explains this?Seamaid
Besides what you linked to, the closest things are this section or this section of the CA Programming Guide, but neither have been updated to include contentsRect. To fix that, click on the "It's good, but..." link at the bottom of the page, and make a request.Rootlet
And really, with an API with as many parameters as CA, you should expect to have to experiment. There's no way the docs can possibly describe what happens with every combination of parameters. The best they can do is describe the pipeline, which is what that 2nd link is trying to do.Rootlet
is there a way to change the identity rect to something other than { {0, 0}, {1, 1} }?Lacewing
What do you mean? contentsRect is just a normalized representation of any rect, regardless of point or pixel dimensions. You can still represent any portion of your layer's contents (or extend it beyond its bounds, if necessary) using that normalized rect.Melar
W
0

The contentsRect property is measured in unit coordinates. Unit coordinates are specified in the range 0 to 1, and are relative values (as opposed to absolute values like points and pixels). In this case, they are relative to the backing image’s dimensions. The default contentsRect is {0, 0, 1, 1}, which means that the entire backing image is visible by default. If we specify a smaller rectangle, the image will be clipped.

It is actually possible to specify a contentsRect with a negative origin or with dimensions larger than {1, 1}. In this case, the outermost pixels of the image will be stretched to fill the remaining area.

You can find more information in Nick Lockwood's book "iOS CoreAnimation Advanced Techniques"

A custom contentsRect (left) and the displayed contents (right)

Workhouse answered 30/10, 2022 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.