Core Animation Basics
Layers Provide the Basis for Drawing and Animations
Layer objects are 2D surfaces organized in a 3D space and are at the heart of everything you do with Core Animation. Like views, layers manage information about the geometry, content, and visual attributes of their surfaces. Unlike views, layers do not define their own appearance. A layer merely manages the state information surrounding a bitmap. The bitmap itself can be the result of a view drawing itself or a fixed image that you specify. For this reason, the main layers you use in your app are considered to be model objects because they primarily manage data. This notion is important to remember because it affects the behavior of animations.
- layer對(duì)象是組織在三維空間的2d層面
- 跟view一樣登疗,layer管理幾何,內(nèi)容和可視屬性炊汹,view跟layer不一樣的時(shí)候岗宣,layer管理圍繞一個(gè)位圖的狀態(tài)信息弹沽。
- layer作為一個(gè)model是因?yàn)樗芾淼氖莇ata业稼!
The Layer-Based Drawing Model
Most layers do not do any actual drawing in your app. Instead, a layer captures the content your app provides and caches it in a bitmap, which is sometimes referred to as the backing store. When you subsequently change a property of the layer, all you are doing is changing the state information associated with the layer object. When a change triggers an animation, Core Animation passes the layer’s bitmap and state information to the graphics hardware, which does the work of rendering the bitmap
- layer捕獲app提供的content并用位圖緩存赤兴。動(dòng)畫觸發(fā)時(shí)腔稀,動(dòng)畫把layer狀態(tài)信息和位圖交給硬件,渲染位圖幽勒。
Manipulating the bitmap in hardware yields much faster animations than could be done in software.
layer是控制靜態(tài)位圖嗜侮,相對(duì)于view-base的繪制技術(shù),view-base每次使用新的參數(shù)來調(diào)用drawrect來重新繪制啥容,這是發(fā)生在cpu的
mainthread,而且耗性能锈颗,layer操作緩存的bitmap來用硬件渲染,也會(huì)達(dá)到同樣效果咪惠。
Layer-Based Animations
The data and state information of a layer object is decoupled from the visual presentation of that layer’s content onscreen
During the course of an animation, Core Animation does all of the frame-by-frame drawing for you in hardware. All you have to do is specify the start and end points of the animation and let Core Animation do the rest. You can also specify custom timing information and animation parameters as needed; however, Core Animation provides suitable default values if you do not.
有兩種坐標(biāo)系統(tǒng)
- point-based coordinate systems
Point-based coordinates are used when specifying values that map directly to screen coordinates or must be specified relative to another layer, such as for the layer’s position property.
- unit coordinate systems
Unit coordinates are used when the value should not be tied to screen coordinates because it is relative to some other value. For example, the layer’s anchorPoint property specifies a point relative to the bounds of the layer itself, which can change.
上圖中击吱,position是在layer中點(diǎn)的點(diǎn),他是其中一個(gè)根據(jù)anchorpoint的值而發(fā)生改變的值
Anchor Points Affect Geometric Manipulations
Layers Can Be Manipulated in Three Dimensions
The transform property of CALayer specifies the transforms that you want to apply both to the layer and its embedded sublayers.
transform是由原作標(biāo)經(jīng)過一個(gè)4緯矩陣變換后得到的坐標(biāo)遥昧,Core Animation已經(jīng)為我們提供了全面的包括creating scale, translation, and rotation matrices and for doing matrix comparisons
各種變換的矩陣實(shí)現(xiàn)
三種layer樹
Objects in the
model layer tree
(or simply “l(fā)ayer tree”) are the ones your app interacts with the most. The objects in this tree are the model objects that store the target values for any animations.Objects in the
presentation tree
contain the in-flight values for any running animations.Objects in the
render tree
perform the actual animations and are private to Core Animation.
layer層級(jí)
一般的基本操作都在model layer tree上面覆醇,每個(gè)model layer都有相關(guān)聯(lián)的presentation tree和render tree,presentation tree 一般用于動(dòng)畫展示炭臭,可以用 presentationLayer獲取動(dòng)畫過程中的layer屬性
Important: You should access objects in the presentation tree only while an animation is in flight. While an animation is in progress, the presentation tree contains the layer values as they appear onscreen at that instant. This behavior differs from the layer tree, which always reflects the last value set by your code and is equivalent to the final state of the animation.
presentation tree獲取的是動(dòng)畫即使的屬性永脓,而layer tree 反應(yīng)的是動(dòng)畫的最終屬性和狀態(tài)
Layers do not handle events, draw content, participate in the responder chain,
Setting Up Layer Objects
Changing the Layer Object Associated with a View
Changing the Layer Class Used by UIView
改變UIView的layer,可以重寫
+ (Class) layerClass {
return [CAMetalLayer class];
}
CALayer子類
Providing a Layer’s Contents
A layer’s content consists of a bitmap containing the visual data you want to display. You can provide the content for that bitmap in one of three ways:
- Assign an image object directly to the layer object’s contents property. (This technique is best for layer content that never, or rarely, changes.)
- Assign a delegate object to the layer and let the delegate draw the layer’s content. (This technique is best for layer content that might change periodically and can be provided by an external object, such as a view.)
- Define a layer subclass and override one of its drawing methods to provide the layer contents yourself. (This technique is appropriate if you have to create a custom layer subclass anyway or if you want to change the fundamental drawing behavior of the layer.)
Using an Image for the Layer’s Content
因?yàn)閘ayer就是一個(gè)bitmap image的容器鞋仍,可以直接賦值content添加圖片常摧,CGImageRef類型的,當(dāng)用layer設(shè)置圖片時(shí)威创,要注意contentsScale 這個(gè)值落午,在點(diǎn)坐標(biāo)系中,一個(gè)點(diǎn)對(duì)應(yīng)contentsScale個(gè)pixel肚豺,給uiview設(shè)置圖片contentsScale是自動(dòng)適應(yīng)屏幕的溃斋,給layer設(shè)置圖片則需要設(shè)置scale
Using a Delegate to Provide the Layer’s Content
代理方法
- displayLayer:
- drawLayer:inContext:,如果代理實(shí)現(xiàn)了displayLayer:就不會(huì)實(shí)現(xiàn)這個(gè)方法。Core Animation creates a bitmap, creates a graphics context to draw into that bitmap, and then calls your delegate method to fill the bitmap. All your delegate method has to do is draw into the provided graphics context.
Providing Layer Content Through Subclassing
- override the layer’s display method and use it to set the contents property of the layer directly.
- Override the layer’s drawInContext: method and use it to draw into the provided graphics context.
Tweaking the Content You Provide
Working with High-Resolution Images
Changing the value of the contentsScale property is only necessary if you are assigning a bitmap to your layer directly.
Adjusting a Layer’s Visual Style and Appearance
Layers Have Their Own Background and Border
Layers Support a Corner Radius
Because it involves applying a transparency mask, the corner radius does not affect the image in the layer’s contents property unless the masksToBounds property is set to YES
Layers Support Built-In Shadows
The opacity value for layer shadows is set to 0 by default, which effectively hides the shadow. Changing the opacity to a nonzero value causes Core Animation to draw the shadow
當(dāng)又要圓角又要shadow的時(shí)候吸申,maskToBounds會(huì)把陰影切掉盐类,可以使用兩個(gè)layer來實(shí)現(xiàn)
Animating Layer Content
- implicit animations 隱式動(dòng)畫 改變layer的屬性
- explicit animation 顯式動(dòng)畫 使用CABaseAnimation等實(shí)現(xiàn),不會(huì)改變layer最終的屬性值呛谜,you must also update the layer’s property as shown in the preceding example.
Implicit and explicit animations normally begin executing after the current run loop cycle ends, and the current thread must have a run loop in order for animations to be executed.
Using a Keyframe Animation to Change Layer Properties
Specifying Keyframe Values
- For properties that take a CGRect (such as the bounds and frame properties), wrap each rectangle in an NSValue object.
- For the layer’s transform property, wrap each CATransform3D matrix in an NSValue object. Animating this property causes the keyframe animation to apply each transform matrix to the layer in turn.
- For the borderColor property, cast each CGColorRef data type to the type id before adding it to the array.
- For properties that take a CGFloat value, wrap each value in an NSNumber object before adding it to the array.
When animating the layer’s contents property, specify an array of CGImageRef data types.
Specifying the Timing of a Keyframe Animation
The calculationMode property defines the algorithm to use in calculating the animation timing.
- Linear and cubic animations—that is, animations where the calculationMode property is set to kCAAnimationLinear or kCAAnimationCubic—use the provided timing information to generate the animation. These modes give you the
maximum control
over the animation timing. - Paced animations—that is, animations where the calculationMode property is set to kCAAnimationPaced or kCAAnimationCubicPaced—
do not rely on the external timing values provided by the keyTimes or timingFunctions properties.
Instead, timing values are calculated implicitly to provide the animation with a constant velocity. - Discrete animations—that is, animations where the calculationMode property is set to kCAAnimationDiscrete—
cause the animated property to jump from one keyframe value to the next without any interpolation(插值).
This calculation mode uses the values in the keyTimes property butignores the timingFunctions
property
Stopping an Explicit Animation While It Is Running
- To remove a single animation object from the layer, call the layer’s
removeAnimationForKey:
method to remove your animation object. This method uses the key that was passed to theaddAnimation:forKey:
method to identify the animation. The key you specify must not be nil. - To remove all animation objects from the layer, call the layer’s
removeAllAnimations
method. This method removes all ongoing animations immediately and redraws the layer using its current state information.
隱式動(dòng)畫不可以停止
When you remove an animation from a layer, Core Animation responds by redrawing the layer using its current values. Because the current values are usually the end values of the animation, this can cause the appearance of the layer to jump suddenly. If you want the layer’s appearance to remain where it was on the last frame of the animation, you can use the objects in the presentation tree to retrieve those final values and set them on the objects in the layer tree
如果立即移除動(dòng)畫在跳,layer會(huì)根據(jù)之前的屬性繪制layer,會(huì)造成畫面突然跳動(dòng)到動(dòng)畫開始的layer的現(xiàn)象隐岛,可以通過presentation樹來獲取停止前的屬性值
Animating Multiple Changes Together
- CAAnimationGroup
- 動(dòng)畫事務(wù)猫妙,更強(qiáng)大
Detecting the End of an Animation
There are two different ways to be notified about the state of an animation:
- Add a completion block to the current transaction using the
setCompletionBlock:
method. When all of the animations in the ``transaction
finish, the transaction executes your completion block. - Assign a delegate to your CAAnimation object and implement the
animationDidStart:
andanimationDidStop:finished:
delegate methods.
If you want to chain two animations together so that one starts when the other finishes, do not use animation notifications. Instead, use the beginTime property of your animation objects to start each one at the desired time. To chain two animations together, set the start time of the second animation to the end time of the first animation. For more information about animation and timing values, see Customizing the Timing of an Animation
如果一個(gè)動(dòng)畫的開始再另一個(gè)動(dòng)畫的結(jié)束,最好不要用上面的方法聚凹,可以根據(jù)動(dòng)畫開始和結(jié)束的時(shí)間
Rules for Modifying Layers in iOS
[UIView animateWithDuration:1.0 animations:^{
// Change the opacity implicitly.
myView.layer.opacity = 0.0;
// Change the position explicitly.
CABasicAnimation* theAnim = [CABasicAnimation animationWithKeyPath:@"position"];
theAnim.fromValue = [NSValue valueWithCGPoint:myView.layer.position];
theAnim.toValue = [NSValue valueWithCGPoint:myNewPosition];
theAnim.duration = 3.0;
[myView.layer addAnimation:theAnim forKey:@"AnimateFrame"];
}];
Both animations start at the same time but the opacity animation runs with the default timing while the position animation runs with the timing specified in its animation object.
Remember to Update View Constraints as Part of Your Animation
Building a Layer Hierarchy
Arranging Layers into a Layer Hierarchy
Adding, Inserting, and Removing Sublayers
When adding and inserting sublayers, you must set the size and position of the sublayer before it appears onscreen. You can modify the size and position of a sublayer after adding it to your layer hierarchy but should get in the habit of setting those values when you create the layer.
Positioning and Sizing Sublayers
You set the size of a sublayer using the bounds property and set its position within its superlayer using the position property. The origin of the bounds rectangle is almost always (0, 0) and the size is whatever size you want for the layer specified in points. The value in the position property is interpreted relative to the layer’s anchor point, which is located in the center of the layer by default. If you do not assign values to these properties, Core Animation sets the initial width and height of the layer to 0 and sets the position to (0, 0).
myLayer.bounds = CGRectMake(0, 0, 100, 100);
myLayer.position = CGPointMake(200, 200);
`Important: Always use integral numbers for the width and height of your layer.`
Sublayers and Clipping
Converting Coordinate Values Between Layers
坐標(biāo)轉(zhuǎn)換
- convertPoint:fromLayer:
- convertPoint:toLayer:
- convertRect:fromLayer:
- convertRect:toLayer:
時(shí)間轉(zhuǎn)換割坠。
In addition to converting point and rectangle values, you can also convert time values between layers using the
convertTime:fromLayer:
andconvertTime:toLayer:
methods. Each layer defines its own local time space and uses that time space to synchronize the beginning and ending of animations with the rest of the system. These time spaces are synchronized by default; however, if you change the animation speed for one set of layers, the time space for those layers changes accordingly. You can use the time conversion methods to to account for any such factors and ensure that the timing of both layers is synchronized.
每個(gè)layer都有自己的時(shí)間空間齐帚,但不同layer的這些時(shí)間一般都是同步的,除非設(shè)置了layer的動(dòng)畫速度彼哼,此時(shí)可用時(shí)間轉(zhuǎn)換函數(shù)
Advanced Animation Tricks
Customizing the Timing of an Animation
- CAAimation 遵循CAMediaTiming protocol
- The CALayer also adopts it so that you can configure some timing-related features for your implicit animations
Each layer has its own local time that it uses to manage animation timing. Normally, the local time of two different layers is close enough that you could specify the same time values for each and the user might not notice anything.
每個(gè)layer的時(shí)間都是相近的
layer’sspeed
property causes the duration of animations on that layer (and its sublayers) to change proportionally.
speed可以改變layer的時(shí)間系統(tǒng)To assist you in making sure time values are appropriate for a given layer, the CALayer class defines the
convertTime:romLayer:
andconvertTime:toLayer:
methods.
可以用上面這兩個(gè)函數(shù)轉(zhuǎn)換時(shí)間系統(tǒng)不同的layer的時(shí)間CACurrentMediaTime function is a convenience function that returns the computer’s current clock time, which the method takes and converts to the layer’s local time.
CACurrentMediaTime
可以獲取標(biāo)準(zhǔn)的時(shí)間对妄,可以用來計(jì)算當(dāng)前l(fā)ayer的時(shí)間
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];
- 兩個(gè)動(dòng)畫銜接用begintime
Pausing and Resuming Animations
- adopt the CAMediaTiming protocol
-(void)pauseLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer {
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Explicit Transactions Let You Change Animation Parameters
Only after you commit the changes for the outermost transaction does Core Animation begin the associated animations
[CATransaction begin]; // Outer transaction
// Change the animation duration to two seconds
[CATransaction setValue:[NSNumber numberWithFloat:2.0f]
forKey:kCATransactionAnimationDuration];
// Move the layer to a new position
theLayer.position = CGPointMake(0.0,0.0);
[CATransaction begin]; // Inner transaction
// Change the animation duration to five seconds
[CATransaction setValue:[NSNumber numberWithFloat:5.0f]
forKey:kCATransactionAnimationDuration];
// Change the zPosition and opacity
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit]; // Inner transaction
[CATransaction commit]; // Outer transaction
Adding Perspective to Your Animations
position
Changing a Layer’s Default Behavior
Disable Actions Temporarily Using the CATransaction Class
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
[aLayer removeFromSuperlayer];
[CATransaction commit];