This chapter describes the components of a layer’s geometry, how they interrelate, and how transform matrices can produce complex visual effects.
Layer Coordinate System
Specifying a Layer’s Geometry
Transforming a Layer’s Geometry
The layer's location and size are expressed using the same coordinate system that the Quartz graphics environment uses. By default, the graphics environment origin (0.0,0.0) is located in the lower left, and values are specified as floating-point numbers that increase up and to the right in coordinate system units. The coordinate system units, the unit square, is the size of a 1.0 by 1.0 rectangle.
Every layer instance defines and maintains its own coordinate system, and all sublayers are positioned, and drawing is done, relative to this coordinate system. Methods are provided to convert points, rectangles and sizes from one layer coordinate system to another. A layer's coordinate system should be considered the base coordinate system for all the content of the layer, including its sublayers.
iPhone OS Note: The default root layer of a UIView
instance uses a flipped coordinate system that matches the default coordinate system of a UIView
instance–the origin is in the top-left and values increase down and to the right. Layers created by instantiating CALayer
directly use the standard Core Animation coordinate system.
While layers and the layer-tree are analogous to Cocoa views and the view hierarchy in many ways, how a layer's geometry is specified is different, and often simpler, manner. All of a layer’s geometric properties, including the layer’s transform matrices, can be implicitly and explicitly animated.
Figure 1 shows the properties used to specify a layer's geometry in context.
The position
property is a CGPoint
that specifies the position of the layer relative to its superlayer, and is expressed in the superlayer's coordinate system.
The bounds
property is a CGRect
that provides the size of the layer (bounds.size
) and the origin (bounds.origin
). The bounds origin is used as the origin of the graphics context when you override a layer's drawing methods.
Layers have an implicit frame
that is a function of the position
, bounds
, anchorPoint
, and transform
properties. Setting a new frame rectangle changes the layer's position
and bounds
properties appropriately, but the frame itself is not stored. When a new frame rectangle is specified the bounds origin is undisturbed, while the bounds size is set to the size of the frame. The layer's position is set to the proper location relative to the anchor point. When you get the frame
property value, it is calculated relative to the position
, bounds
, and anchorPoint
properties.
The anchorPoint
property is a CGPoint
that specifies a location within the bounds of a layer that corresponds with the position coordinate. The anchor point specifies how the bounds are positioned relative to the position property, as well as serving as the point that transforms are applied around. It is expressed in the unit coordinate system-the lower left of the layer bounds is 0.0,0.0, and the upper right is 1.0,1.0.
When you specify the frame of a layer, position
is set relative to the anchor point. When you specify the position of the layer, bounds
is set relative to the anchor point.
Figure 2 shows three example values for an anchor point.
The default value for anchorPoint
is (0.5,0.5) which corresponds to the center of the layer's bounds (shown as point A in Figure 2.) Point B shows the position of an anchor point set to (0.0,0.5). Finally, point C (1.0,0.0) causes specifies that the layer’s position
is set to the bottom right corner of the frame.
The relationship of the frame
, bounds
, position
, and anchorPoint
properties is shown in Figure 3.
In this example the anchorPoint
is set to the default value of (0.5,0.5), which corresponds to the center of the layer. The position
of the layer is set to (100.0,100.0), and the bounds
is set to the rectangle (0.0, 0.0, 120.0, 80.0). This causes the frame property to be calculated as (40.0, 60.0, 120.0, 80.0).
If you created a new layer, and set only the layer’s frame property to (40.0, 60.0, 120.0, 80.0), the position
property would be automatically set to (100.0,100.0), and the bounds property to (0.0, 0.0, 120.0, 80.0).
Figure 4 shows a layer with the same frame
rectangle as the layer in Figure 3. However, in this case the anchorPoint
of the layer is set to (0.0,0.0), which corresponds with the bottom left corner of the layer.
With the frame set to (40.0, 60.0, 120.0, 80.0), the value of the bounds
property is the same, but the value of the position
property has changed.
Another aspect of layer geometry that differs from Cocoa views is that you can specify a radius that is used to round the corners of the layer. The cornerRadius
property specifies a radius the layer uses when drawing content, clipping sublayers, and drawing the border and shadow.
The zPosition
property specifies the z-axis component of the layer's position. The zPosition
is intended to be used to set the visual position of the layer relative to its sibling layers. It should not be used to specify the order of layer siblings, instead reorder the layer in the sublayer array.
Once established, you can transform a layer's geometry using matrix transformations. The Transform
data structure defines a homogenous three-dimensional transform (a 4 by 4 matrix of CGFloat
values) that is used to rotate, scale, offset, skew, and apply perspective transformations to a layer.
Two layer properties specify transform matrices: transform
and sublayerTransform
. The matrix specified by the transform
property is applied to the layer and its sublayers relative to the layer's anchorPoint
. Figure 3 shows how rotation and scaling transforms affect a layer when using an anchorPoint of (0.5,0.5), the default value. Figure 4 shows how the same transform matrices affect a layer when an anchorPoint of (0.0,0.0). The matrix specified by the sublayerTransform
property is applied only to the layer’s sublayers, rather than to the layer itself.
You create and modify CATransform3D
data structures in one of the following ways:
using the CATransform3D
functions
modifying the data structure members directly
using key-value coding and key paths.
The constant CATransform3DIdentity
is the identity matrix, a matrix that has no scale, rotation, skewing, or perspective applied. Applying the identity matrix to a layer causes it to be displayed with its default geometry.
The transform functions available in Core Animation operate on matrices. You can use these functions (shown in Table 1) to construct a matrix that you later apply to a layer or its sublayers by modifying the transform or sublayerTransform properties respectively. The transform functions either operate on, or return, a CATransform3D
data structure. This enables you to construct simple or complex transforms that you can readily reuse.
Function | Use |
---|---|
Returns a transform that translates by '(tx, ty, tz)'. t' = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]. | |
Translate 't' by '(tx, ty, tz)' and return the result: * t' = translate(tx, ty, tz) * t. | |
Returns a transform that scales by `(sx, sy, sz)': * t' = [sx 0 0 0; 0 sy 0 0; 0 0 sz 0; 0 0 0 1]. | |
Scale 't' by '(sx, sy, sz)' and return the result: * t' = scale(sx, sy, sz) * t. | |
Returns a transform that rotates by 'angle' radians about the vector '(x, y, z)'. If the vector has length zero the identity transform is returned. | |
Rotate 't' by 'angle' radians about the vector '(x, y, z)' and return the result. t' = rotation(angle, x, y, z) * t. |
The angles of rotation is specified in radians rather than degrees. The following functions allow you to convert between radians and degrees.
CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;}; |
CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180 / M_PI;}; |
Core Animation provides a transform function that inverts a matrix, CATransform3DInvert
. Inversion is generally used to provide reverse transformation of points within transformed objects. Inversion can be useful when you need to recover a value that has been transformed by a matrix: invert the matrix, and multiply the value by the inverted matrix, and the result is the original value.
Functions are also provided that allow you to convert a CATransform3D
matrix to a CGAffineTransform
matrix, if the CATransform3D
matrix can be expressed as such.
Function | Use |
---|---|
Returns a | |
Returns | |
Returns the affine transform represented by the passed |
Functions are provided for comparing transform matrices for equality with the identity matrix, or another transform matrix.
Function | Use |
---|---|
Returns | |
Returns |
You can modify the value of any of the CATransform3D
data structure members as you would any other data structure. Listing 1 contains the definition of the CATransform3D
data structure, the structure members are shown in their corresponding matrix positions.
Listing 1 CATransform3D structure
struct CATransform3D |
{ |
CGFloat m11, m12, m13, m14; |
CGFloat m21, m22, m23, m24; |
CGFloat m31, m32, m33, m34; |
CGFloat m41, m42, m43, m44; |
}; |
typedef struct CATransform3D CATransform3D; |
The example in Listing 2 illustrates how to configure a CATransform3D
as a perspective transform.
Listing 2 Modifying the CATransform3D data structure directly
CATransform3D aTransform = CATransform3DIdentity; |
// the value of zDistance affects the sharpness of the transform. |
zDistance = 850; |
aTransform.m34 = 1.0 / -zDistance; |
Core Animation extends the key-value coding protocol to allow getting and setting of the commonly values of a layer's CATransform3D
matrix through key paths. Table 4 describes the key paths for which a layer’s transform
and sublayerTransform
properties are key-value coding and observing compliant.
Field Key Path | Description |
---|---|
| The rotation, in radians, in the x axis. |
| The rotation, in radians, in the y axis. |
| The rotation, in radians, in the z axis. |
| The rotation, in radians, in the z axis. This is identical to setting the |
| Scale factor for the x axis. |
| Scale factor for the y axis. |
| Scale factor for the z axis. |
| Average of all three scale factors. |
| Translate in the x axis. |
| Translate in the y axis. |
| Translate in the z axis. |
| Translate in the x and y axis. Value is an NSSize or CGSize. |
You can not specify a structure field key path using Objective-C 2.0 properties. This will not work:
myLayer.transform.rotation.x=0; |
Instead you must use setValue:forKeyPath:
or valueForKeyPath:
as shown below:
[myLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"transform.rotation.x"]; |
© 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-11-13)