Core Animation classes can be grouped into several categories:
-
Layer classes that provide content for display
-
Animation and timing classes
-
Layout and constraint classes
-
A transaction class that groups multiple layer changes into an atomic update
The coordinate system for layers differs depending on the current platform. In iOS, the default coordinate system origin is in the top-left corner of the layer and positive values extend down and to the right of that origin point. In Mac OS X, the default coordinate system origin is in the lower-left corner of the layer and positive values extend up and to the right of that point. All coordinate values are specified as floating-point numbers. And any layers you create on a given platform use the default coordinate system associated with that platform.
Every layer object defines and maintains its own coordinate system, and all content in a layer is positioned relative to this coordinate system. This is true both for the layer contents itself and for any sublayers. Because each layer defines its own coordinate system, the class provides methods to convert point, rectangle and size values from the coordinate system of one layer to another.
Some layer-related properties measure their values using the unit coordinate space. The unit coordinate space is a way of specifying values relative to the bounds of the layer but without tying that property to the exact bounds values. A given x or y coordinate in the unit coordinate space is always in the range of 0.0 to 1.0. Specifying a value of 0.0 along the x axis yields a point on the left edge of the layer while specifying a value of 1.0 yields a point on the right edge of the layer. (For y values, which value is along the top edge and which value is along the bottom edge depends on the underlying platform and follows the same rules as previously described.) A point of (0.5, 0.5) yields a point in the exact center of the layer.
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 (0.0,0.0) value is located closest to the layer’s origin and (1.0,1.0) is located in the opposite corner. Applying a transform to the layer’s parent (if one exists) can alter the anchorPoint
orientation, depending on the parent’s coordinate system on the y-axis.
Once established, you can transform a layer's geometry using matrix transformations. The 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.
(1)Transform Functions
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. |
Function | Use |
---|---|
| Returns a |
| Returns |
| Returns the affine transform represented by the passed |
Function | Use |
---|---|
| Returns |
| Returns |
(2)Modifying the transform Data 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; |
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; |
(3)Modifying a Transform Using Key Paths
Core Animation extends the key-value coding protocol to allow getting and setting of the common 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 or
as shown below:
[myLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"transform.rotation.x"]; |
NSView
or UIView
has superview and subviews, a Core Animation layer has a superlayer and sublayers. Method | Result |
---|---|
| Appends the layer to the receiver’s sublayers array. |
| Inserts the layer as a sublayer of the receiver at the specified index. |
| Inserts the layer into the receiver’s sublayers array, below the specified sublayer. |
| Inserts the layer into the receiver’s sublayers array, above the specified sublayer. |
| Removes the receiver from the sublayers array or mask property of the receiver’s superlayer. |
| Replaces the layer in the receiver’s sublayers array with the specified new layer. |
After a layer has been created, you can move and resize it programmatically simply by changing the value of the layer’s geometry properties: frame
, bounds
, position
, anchorPoint
, or zPosition
.
If a layer’s needsDisplayOnBoundsChange
property is YES, the layer’s content is recached when the layer’s bounds changes. By default the needsDisplayOnBoundsChange
property is no.
CALayer
provides a mechanism for automatically moving and resizing sublayers in response to their superlayer being moved or resized. In many cases simply configuring the autoresizing mask for a layer provides the appropriate behavior for an application.
A layer's autoresizing mask is specified by combining the CAAutoresizingMask
constants using the bitwise OR
operator and the layer'sautoresizingMask
property to the resulting value.
Autoresizing Mask | Description |
---|---|
| If set, the layer's height changes proportionally to the change in the superlayer's height. Otherwise, the layer's height does not change relative to the superlayer's height. |
| If set, the layer's width changes proportionally to the change in the superlayer's width. Otherwise, the layer's width does not change relative to the superlayer's width. |
| If set, the layer's left edge is repositioned proportionally to the change in the superlayer's width. Otherwise, the layer's left edge remains in the same position relative to the superlayer's left edge. |
| If set, the layer's right edge is repositioned proportionally to the change in the superlayer's width. Otherwise, the layer's right edge remains in the same position relative to the superlayer. |
| If set, the layer's top edge is repositioned proportionally to the change in the superlayer's height. Otherwise, the layer's top edge remains in the same position relative to the superlayer. |
| If set, the layer's bottom edge is repositioned proportional to the change in the superlayer's height. Otherwise, the layer's bottom edge remains in the same position relative to the superlayer. |
(3)Clipping SubLayers
The value of a layer’smasksToBounds
property determines if sublayers are clipped to the parent. The default value of the masksToBounds
property is NO
, which prevents sublayers from being clipped to the parent.
automatically creates an instance of a CALayer
class and sets it as the value of the view’s layer
property. You can add sublayers to the view’s layer as needed. You specify the content of a CALayer
instance in one of the following ways:
-
Explicitly set the
property of a layer instance using a
that contains the content image.
-
Specify a delegate that provides, or draws, the content.
-
Subclass
CALayer
and override one of the display methods.
(1)Setting the Content Property
CALayer *theLayer; |
// create the layer and set the bounds and position |
theLayer=[CALayer layer]; |
theLayer.position=CGPointMake(50.0f,50.0f); |
theLayer.bounds=CGRectMake(0.0f,0.0f,100.0f,100.0f); |
// set the contents property to a CGImageRef |
// specified by theImage (loaded elsewhere) |
theLayer.contents=theImage; |
(2)(3)略
(4)Positioning Content Within a Layer
The CALayer
property allows you to position and scale the layer’s
contents
image within the layer bounds. By default, the content image fills the layer’s bounds entirely, ignoring the natural aspect ratio of the image.
Using the contentsGravity
positioning constants you can specify that the image is placed along any of the layer’s edges, in the layer’s corners, or centered within the layer’s bounds. However, when using the positioning constants the property is not used.
Position constant | Description |
---|---|
| Positions the content image in the top left corner of the layer. |
| Positions the content image horizontally centered along the top edge of the layer. |
| Positions the content image in the top right corner of the layer. |
| Positions the content image vertically centered on the left edge of the layer. |
| Positions the content image at the center of the layer. |
| Positions the content image vertically centered on the right edge of the layer. |
| Positions the content image in the bottom left corner of the layer. |
| Positions the content image centered along the bottom edge of the layer. |
| Positions the content image in the top right corner of the layer. |
Scaling constant | Description |
---|---|
| Resize the content image to completely fill the layer bounds, potentially ignoring the natural aspect of the content. This is the default. |
| Resize the content image to scale such that it is displayed as large as possible within the layer bounds, yet still retains its natural aspect. |
| Resize the content image to scale such that it is displayed filling the layer bounds, yet retaining its natural aspect. This may cause the content to extend outside the layer bounds. |
Core Animation provides an expressive set of animation classes you can use in your application:
-
CABasicAnimation
provides simple interpolation between values for a layer property. -
CAKeyframeAnimation
provides support for key frame animation. You specify the key path of the layer property to be animated, an array of values that represent the value at each stage of the animation, as well as arrays of key frame times and timing functions. As the animation runs, each value is set in turn using the specified interpolation. -
CATransition
provides a transition effect that affects the entire layer's content. It fades, pushes, or reveals layer content when animating. The stock transition effects can be extended by providing your own custom Core Image filters. -
CAAnimationGroup
allows an array of animation objects to be grouped together and run concurrently.
In addition to specifying the type of animation to perform, you must also specify the duration of the animation, the pacing (how the interpolated values are distributed across the duration), if the animation is to repeat and how many times, whether it should automatically reverse when each cycle is completed, and its visual state when the animation is completed. The animation classes and the CAMediaTiming
protocol provides all this functionality and more.
(2)Implicit Animation
Core Animation’s implicit animation model assumes that all changes to animatable layer properties should be gradual and asynchronous. Dynamically animated scenes can be achieved without ever explicitly animating layers. Changing the value of an animatable layer property causes the layer to implicitly animate the change from the old value to the new value. While an animation is in-flight, setting a new target value causes the animation transition to the new target value from its current state.
Listing 1 shows how simple it is to trigger an implicit animation that animates a layer from its current position to a new position.
Listing 1 Implicitly animating a layer’s position property
// assume that the layer is current positioned at (100.0,100.0) |
theLayer.position=CGPointMake(500.0,500.0); |
You can implicitly animate a single layer property at a time, or many. You can also implicitly animate several layers simultaneously. The code in Listing 2 causes four implicit animations to occur simultaneously.
Listing 2 Implicitly animating multiple properties of multiple layers
// animate theLayer's opacity to 0 while moving it |
// further away in the layer |
theLayer.opacity=0.0; |
theLayer.zPosition=-100; |
// animate anotherLayer's opacity to 1 |
// while moving it closer in the layer |
anotherLayer.opacity=1.0; |
anotherLayer.zPosition=100.0; |
Implicit animations use the duration specified in the default animation for the property, unless the duration has been overridden in an implicit or explicit transaction.
(3)Explicit Animation
Core Animation also supports an explicit animation model. The explicit animation model requires that you create an animation object, and set start and end values. An explicit animation won’t start until you apply the animation to a layer. The code fragment in Listing 3 creates an explicit animation that transitions a layer’s opacity from fully opaque to fully transparent, and back over a 3 second duration. The animation doesn’t begin until it is added to the layer.
Listing 3 Explicit animation
CABasicAnimation *theAnimation; |
theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"]; |
theAnimation.duration=3.0; |
theAnimation.repeatCount=2; |
theAnimation.autoreverses=YES; |
theAnimation.fromValue=[NSNumber numberWithFloat:1.0]; |
theAnimation.toValue=[NSNumber numberWithFloat:0.0]; |
[theLayer addAnimation:theAnimation forKey:@"animateOpacity"]; |
Explicit animations are especially useful when creating animations that run continuously. Listing 4 shows how to create an explicit animation that applies a CoreImage bloom filter to a layer, animating its intensity. This causes the “selection layer” to pulse, drawing the user’s attention.
Listing 4 Continuous explicit animation example
// The selection layer will pulse continuously. |
// This is accomplished by setting a bloom filter on the layer |
// create the filter and set its default values |
CIFilter *filter = [CIFilter filterWithName:@"CIBloom"]; |
[filter setDefaults]; |
[filter setValue:[NSNumber numberWithFloat:5.0] forKey:@"inputRadius"]; |
// name the filter so we can use the keypath to animate the inputIntensity |
// attribute of the filter |
[filter setName:@"pulseFilter"]; |
// set the filter to the selection layer's filters |
[selectionLayer setFilters:[NSArray arrayWithObject:filter]]; |
// create the animation that will handle the pulsing. |
CABasicAnimation* pulseAnimation = [CABasicAnimation animation]; |
// the attribute we want to animate is the inputIntensity |
// of the pulseFilter |
pulseAnimation.keyPath = @"filters.pulseFilter.inputIntensity"; |
// we want it to animate from the value 0 to 1 |
pulseAnimation.fromValue = [NSNumber numberWithFloat: 0.0]; |
pulseAnimation.toValue = [NSNumber numberWithFloat: 1.5]; |
// over a one second duration, and run an infinite |
// number of times |
pulseAnimation.duration = 1.0; |
pulseAnimation.repeatCount = HUGE_VALF; |
// we want it to fade on, and fade off, so it needs to |
// automatically autoreverse.. this causes the intensity |
// input to go from 0 to 1 to 0 |
pulseAnimation.autoreverses = YES; |
// use a timing curve of easy in, easy out.. |
pulseAnimation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]; |
// add the animation to the selection layer. This causes |
// it to begin animating. We'll use pulseAnimation as the |
// animation key name |
[selectionLayer addAnimation:pulseAnimation forKey:@"pulseAnimation"]; |
(4)Starting and Stopping Explicit Animations
You start an explicit animation by sending aaddAnimation:forKey:
message to the target layer, passing the animation and an identifier as parameters. Once added to the target layer the explicit animation will run until the animation completes, or it is removed from the layer. The identifier used to add an animation to a layer is also used to stop it by invoking removeAnimationForKey:
. You can stop all animations for a layer by sending the layer a removeAllAnimations
message. An action object is an object that responds to an action identifier via the CAAction
protocol. Action identifiers are named using standard dot-separated key paths. A layer is responsible for mapping action identifiers to the appropriate action object. When the action object for the identifier is located that object is sent the message defined by theCAAction
protocol.
The CALayer
class provides default action objects–instances of CAAnimation
, a CAAction
protocol compliant class–for all animatable layer properties. CALayer
also defines the following action triggers that are not linked directly to properties, as well as the action identifiers in Table 1.
Trigger | Action identifier |
---|---|
A layer is inserted into a visible layer-tree, or the | The action identifier constant |
A layer is removed from a visible layer-tree, or the | The action identifier constant |
A layer replaces an existing layer in a visible layer tree using | The action identifier constant |
When an action trigger occurs, the layer’s actionForKey:
method is invoked. This method returns an action object that corresponds to the action identifier passed as the parameter, or nil
if no action object exists.
When the CALayer
implementation of actionForKey:
is invoked for an identifier the following search pattern is used:
-
If the layer has a delegate, and it implements the method
actionForLayer:forKey:
it is invoked, passing the layer, and the action identifier as parameters. The delegate’sactionForLayer:forKey:
implementation should respond as follows:-
Return an action object that corresponds to the action identifier.
-
Return
nil
if it doesn’t handle the action identifier. -
Return
NSNull
if it doesn’t handle the action identifier and the search should be terminated.
-
-
The layer’s
actions
dictionary is searched for an object that corresponds to the action identifier. -
The layer’s
style
property is searched for anactions
dictionary that contains the identifier. -
The layer’s class is sent a
defaultActionForKey:
message. It will return an action object corresponding to the identifier, ornil
if not found.