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.

Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
Steven Oxley
  • 6,563
  • 6
  • 43
  • 55

2 Answers2

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.

Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
  • Great answer. That makes more sense. Do you know if there's any official documentation that explains this? – Steven Oxley Apr 12 '12 at 05:43
  • Besides what you linked to, the closest things are [this section](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/ProvidingCALayerContent.html#//apple_ref/doc/uid/TP40006642-SW12) or [this section](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/LayerVisProps.html#//apple_ref/doc/uid/TP40006074-SW1) 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. – Kurt Revis Apr 12 '12 at 05:54
  • 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. – Kurt Revis Apr 12 '12 at 05:56
  • is there a way to change the identity rect to something other than { {0, 0}, {1, 1} }? – user102008 Jun 05 '15 at 00:43
  • 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. – CIFilter Jan 20 '17 at 07:46
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)