你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 核心動畫編程指南Core Animation Programming Guide - iOS

核心動畫編程指南Core Animation Programming Guide - iOS

編輯:IOS開發綜合

1 有關核心動畫

 


\

 

1.1 概覽

1.1.1 Core Animation 管理應用的內容

核心是 layer objects,

1.1.2 更改 layer 觸發動畫

Like views, layer objects have a bounds rectangle, a position onscreen, an opacity, a transform, and many other visually-oriented properties that can be modified. 更改這些屬性的時候有隱式動畫,可以明確指定動畫行為。

1.1.3 layer可以組織成層級結構

1.1.4 action 讓你更改圖層的默認行為

隱式layer動畫是使用 action objects。可以創建自己的 action objects ,實現自定義動畫,或者也能實現其他類型的行為。

1.2 如果使用這個文檔

1.3 預備工作

先熟悉 View Programming Guide for iOS.

核心動畫基礎

layer 提供繪圖和動畫的基礎

Layer objects 對核心。layer只是管理內容和可視化屬性,所以可以將layer想成 model 對象

基於 layer 的繪圖模型

 


核心動畫如何繪制內容

 

對於 view 中調用 drawRect: 方法,非常的損耗,因為這在線程上使用CPU。核心動畫通過在硬件上緩存位圖來達到同樣或相似的效果。

基於 layer 的動畫

 


可以在 layer 上執行動畫的例子

 

layer 對象定義自己的幾何

layer 也有像view 有的一些屬性,frame bounds,並且也有類似 anchor poing(錨點)這種 view 沒有的屬性。

layer 使用兩種類型的坐標系

point-based coordinate systems 和 unit coordinate systems

通常使用 point-based 坐標系指定 layer 的大小和位置,

 


iOS 和 OS X 的默認 layer geometries

 

unit coordinate system (單位坐標系)是用來表示當 layer 的大小變化的時候哪些屬性可能改變。可以認為單位坐標系指定所有可能變化值的百分比。

 


The default unit coordinate systems for iOS and OS X

 

錨點影響幾何操作

 


How the anchor point affects the layer’s position prZ喎?/kf/ware/vc/vcGVydHk=" src="/uploadfile/Collfiles/20160908/20160908091844351.jpg" />

 

 


How the anchor point affects layer transformations

 

layer 可以在三維空間中操作

 


Converting a coordinate using matrix math

 

 


Matrix configurations for common transformations

 

Core Animation Functions Reference.

layer 樹反映了動畫狀態的不同方面

有3個 layer 對象集合:

model layer tree 中的對象是模型對象,存儲動畫的目標值 presentation tree包含動畫運行中的值。你應該從來都不要去修改這個 tree 中的對象。使用這些對象讀取當前動畫的值,或者使用這些值開始新的動畫。 render tree 中的對象執行實際的動畫,這是核心動畫私有的

 


Layers associated with a window

 

 


The layer trees for a window

 

layer 和 view 之間的關系

layer 不是 view 的替代品,不能單獨靠layer 對象創建一個可視化的界面。layer 提供了 view 的基礎。layer 使得view內容的繪制和動畫更加有效,並且動畫有較高的幀率,就是更流暢。layer不能處理事件,不能繪制內容,不能參與到響應鏈等等。所以應用必須有一個或多個 view 來處理這種交互

設置 layer 對象

激活核心動畫支持

更改與視圖相關的 layer 對象

改變 UIView 使用的 layer class

重寫 layerClass 類方法 返回想要替換的 類對象。

指定 view 的 layer 類

+ (Class) layerClass {
   return [CAMetalLayer class];
}

Changing the Layer Class Used By NSView

不同的 layer 類提供專屬行為

CALayer子類及其用法

Class Usage                                            

給 layer 提供內容

3種方式給layer的位圖提供數據:

直接給layer對象的 contents 屬性賦值一個 image 對象。這是最好的方法 給layer賦值一個代理對象,並讓代理繪制 layer 的內容。(適合內容周期性的變化,比如隨著 view變化) 定義一個 layer 子類,並重寫一個它的繪制方法

給 layer 內容設置圖像

將image 賦值給 layer必須是 CGImageRef 類型。

使用代理給layer提供內容

代理實現 displayLayer: 方法

- (void)displayLayer:(CALayer *)theLayer {
    // Check the value of some state property
    if (self.displayYesImage) {
        // Display the Yes image
        theLayer.contents = [someHelperObject loadStateYesImage];
    }
    else {
        // Display the No image
        theLayer.contents = [someHelperObject loadStateNoImage];
    }
}

代理實現 drawLayer:inContext: 方法

- (void)drawLayer:(CALayer *)theLayer inContext:(CGContextRef)theContext {
    CGMutablePathRef thePath = CGPathCreateMutable();

    CGPathMoveToPoint(thePath,NULL,15.0f,15.f);
    CGPathAddCurveToPoint(thePath,
                          NULL,
                          15.f,250.0f,
                          295.0f,250.0f,
                          295.0f,15.0f);

    CGContextBeginPath(theContext);
    CGContextAddPath(theContext, thePath);

    CGContextSetLineWidth(theContext, 5);
    CGContextStrokePath(theContext);

    // Release the path
    CFRelease(thePath);
}

通過子類給 layer 提供內容

重寫 layer 的 display 方法,並使用它直接設置contents屬性 重寫 layer 的 drawInContext: 方法,並使用它來繪制圖像內容

調整提供的內容

 


Position-based gravity constants for layers

 

layer 的 contentsGravity 屬性模式的設置是 kCAGravityResize 常量。

 


Scaling-based gravity constants for layers

 

高分辨率圖像

調整圖層的視覺風格和外觀

layer 有自己的背景和邊界

 


Adding a border and background to a layer

 

layer 支持半徑圓角

 


\

 

layer 支持內建陰影

 


\

 

OS X 的view 添加過濾效果

iOS 不能給 layer 對象添加過濾器

對於 OS X 性能影響的 layer 重回策略

給 layer 添加自定義屬性

Animating Layer Content

修改 layer 屬性,達到簡單動畫效果

精確的動畫,需要創建一個 CABasicAnimation 對象,使用這個對象來配置參數。

CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
fadeAnim.toValue = [NSNumber numberWithFloat:0.0];
fadeAnim.duration = 1.0;
[theLayer addAnimation:fadeAnim forKey:@"opacity"];

// Change the actual data value in the layer to the final value.
theLayer.opacity = 0.0;

使用關鍵幀動畫來改變 layer 的屬性

// create a CGPath that implements two arcs (a bounce)
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL,74.0,74.0);
CGPathAddCurveToPoint(thePath,NULL,74.0,500.0,
                                   320.0,500.0,
                                   320.0,74.0);
CGPathAddCurveToPoint(thePath,NULL,320.0,500.0,
                                   566.0,500.0,
                                   566.0,74.0);

CAKeyframeAnimation * theAnimation;

// Create the animation object, specifying the position property as the key path.
theAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
theAnimation.path=thePath;
theAnimation.duration=5.0;

// Add the animation to the layer.
[theLayer addAnimation:theAnimation forKey:@"position"];

指定 keyframe 的值

在動畫運行的時候,停止動畫

removeAnimationForKey: removeAllAnimations

只能移除顯示動畫,不能移除隱式動畫。

多個動畫一起變化

// Animation 1
CAKeyframeAnimation* widthAnim = [CAKeyframeAnimation animationWithKeyPath:@"borderWidth"];
NSArray* widthValues = [NSArray arrayWithObjects:@1.0, @10.0, @5.0, @30.0, @0.5, @15.0, @2.0, @50.0, @0.0, nil];
widthAnim.values = widthValues;
widthAnim.calculationMode = kCAAnimationPaced;

// Animation 2
CAKeyframeAnimation* colorAnim = [CAKeyframeAnimation animationWithKeyPath:@"borderColor"];
NSArray* colorValues = [NSArray arrayWithObjects:(id)[UIColor greenColor].CGColor,
            (id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor,  nil];
colorAnim.values = colorValues;
colorAnim.calculationMode = kCAAnimationPaced;

// Animation group
CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:colorAnim, widthAnim, nil];
group.duration = 5.0;

[myLayer addAnimation:group forKey:@"BorderChanges"];

檢測動畫的結束

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: and animationDidStop:finished: delegate methods.

基於 layer 的view 怎麼做動畫

iOS 中修改 layer 的規則

[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"];
}];

建立 layer 層級

將 layer 放入 layer層級中

添加、插入、移除 sublayer

 


\

 

sublayer 的位置和大小

bounds 、position

myLayer.bounds = CGRectMake(0, 0, 100, 100);
myLayer.position = CGPointMake(200, 200);

重點:對於 layer 的寬高總是使用整數

layer 層級如何影響動畫

speed 屬性,動畫速度的倍數。

調整layer層級的布局

Core Animation supports several options for adjusting the size and position of sublayers in response to changes to their superlayer. In iOS, the pervasive use of layer-backed views makes the creation of layer hierarchies less important; only manual layout updates are supported. For OS X, several other options are available that make it easier to manage your layer hierarchies

sublayer 和 cliping

masksToBounds 屬性設置 YES,就可以啟用自動裁剪

 


\

 

在layer 之間轉換坐標值

convertPoint:fromLayer: convertPoint:toLayer: convertRect:fromLayer: convertRect:toLayer:

還有 convertTime:fromLayer 和 convertTime:toLayer

高級動畫技巧

過渡動畫支持更改 layer 可見性

創建 CATransition 對象 ,並添加給 layer。

Listing 5-1 shows the code used to create an animated push transition between two views. In the example, both myView1 and myView2 are located at the same position in the same parent view but only myView1 is currently visible. The push transition causes myView1 to slide out to the left and fade until it is hidden while myView2 slides in from the right and becomes visible. Updating the hidden property of both views ensures that the visibility of both views is correct at the end of the animation.

CATransition* transition = [CATransition animation];
transition.startProgress = 0;
transition.endProgress = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0;

// Add the transition animation to both layers
[myView1.layer addAnimation:transition forKey:@"transition"];
[myView2.layer addAnimation:transition forKey:@"transition"];

// Finally, change the visibility of the layers.
myView1.hidden = YES;
myView2.hidden = NO;

自定義動畫的時間

CAMediaTiming 協議。CAAnimation 和 CALayer 都遵守了這個協議。


#import 
#import 
#import 

/* The CAMediaTiming protocol is implemented by layers and animations, it
 * models a hierarchical timing system, with each object describing the
 * mapping from time values in the object's parent to local time.
 *
 * Absolute time is defined as mach time converted to seconds. The
 * CACurrentMediaTime function is provided as a convenience for querying the
 * current absolute time.
 *
 * The conversion from parent time to local time has two stages:
 *
 * 1. conversion to "active local time". This includes the point at
 * which the object appears in the parent's timeline, and how fast it
 * plays relative to the parent.
 *
 * 2. conversion from active to "basic local time". The timing model
 * allows for objects to repeat their basic duration multiple times,
 * and optionally to play backwards before repeating. */

@class NSString;

NS_ASSUME_NONNULL_BEGIN

@protocol CAMediaTiming

/* The begin time of the object, in relation to its parent object, if
 * applicable. Defaults to 0. */

@property CFTimeInterval beginTime;

/* The basic duration of the object. Defaults to 0. */

@property CFTimeInterval duration;

/* The rate of the layer. Used to scale parent time to local time, e.g.
 * if rate is 2, local time progresses twice as fast as parent time.
 * Defaults to 1. */

@property float speed;

/* Additional offset in active local time. i.e. to convert from parent
 * time tp to active local time t: t = (tp - begin) * speed + offset.
 * One use of this is to "pause" a layer by setting `speed' to zero and
 * `offset' to a suitable value. Defaults to 0. */

@property CFTimeInterval timeOffset;

/* The repeat count of the object. May be fractional. Defaults to 0. */

@property float repeatCount;

/* The repeat duration of the object. Defaults to 0. */

@property CFTimeInterval repeatDuration;

/* When true, the object plays backwards after playing forwards. Defaults
 * to NO. */

@property BOOL autoreverses;

/* Defines how the timed object behaves outside its active duration.
 * Local time may be clamped to either end of the active duration, or
 * the element may be removed from the presentation. The legal values
 * are `backwards', `forwards', `both' and `removed'. Defaults to
 * `removed'. */

@property(copy) NSString *fillMode;

@end

/* `fillMode' options. */

CA_EXTERN NSString * const kCAFillModeForwards
    __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAFillModeBackwards
    __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAFillModeBoth
    __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAFillModeRemoved
    __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);

NS_ASSUME_NONNULL_END

得到 layer 的當前 local time

CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];

暫停和重新開始動畫

-(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;
}

顯式 Transactions 可以更改動畫參數

CATransaction 類

創建顯式的 transaction

[CATransaction begin];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit];

修改動畫的默認持續時間

[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
                 forKey:kCATransactionAnimationDuration];
// Perform the animations
[CATransaction commit];

嵌套顯式 transaction

[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

給動畫添加透視

給 parent layer 添加透視變化

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/eyePosition;

// Apply the transform to a parent layer.
myParentLayer.sublayerTransform = perspective;

改變 layer 的默認行為

CAAction 協議

/** Action (event handler) protocol. **/

@protocol CAAction

/* Called to trigger the event named 'path' on the receiver. The object
 * (e.g. the layer) on which the event happened is 'anObject'. The
 * arguments dictionary may be nil, if non-nil it carries parameters
 * associated with the event. */

- (void)runActionForKey:(NSString *)event object:(id)anObject
    arguments:(nullable NSDictionary *)dict;

@end

自定義操作對象采用CAAction協議

action 對象必須被安裝在 layer 上,才能有效果

核心動畫尋找 action 對象的順序:

如果 layer 有一個 delegate, 並且delegate 實現了 actionForLayer:forKey 方法,layer調用這個方法。delegate 必須做下面幾件事之一:
針對 key 返回 action 對象 沒有它沒有 handle the action 就返回 nil,這種情況會接著尋找 搜尋到末尾的時候立即返回 NSNull 對象 在 layer 的 actions 字典中尋找給定的 key 在 style 字典中尋找包含 key 的 actions 字典(總而言之,style 字典包含了一個 key 為 actions ,value 也是一個字典。layer 在這第二個字典中尋找給定的 key) layer 調用它的 defaultActionForKey: 類方法 layer 執行核心動畫定義的隱式 action

使用 layer 代理對象提供 action

- (id)actionForLayer:(CALayer *)theLayer
                        forKey:(NSString *)theKey {
    CATransition *theAnimation=nil;

    if ([theKey isEqualToString:@"contents"]) {

        theAnimation = [[CATransition alloc] init];
        theAnimation.duration = 1.0;
        theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        theAnimation.type = kCATransitionPush;
        theAnimation.subtype = kCATransitionFromRight;
    }
    return theAnimation;
}

使用 CATransaction 類暫時禁用 action

Temporarily disabling a layer’s actions

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
                 forKey:kCATransactionDisableActions];
[aLayer removeFromSuperlayer];
[CATransaction commit];

提升動畫性能

為 OS X Views 選擇最佳的重繪策略

在 OS X 中更新 layer 來優化 rendering path

通用技巧和竅門

盡可能使用不透明的 layer

對 CAShapeLayer 對象使用更簡單的 path

對相同 layer 明確設置 layer 內容

總是將 layer 的大小設置為 整數值

根據需要使用異步來渲染 layer

drawsAsynchronously 屬性

當給 layer 添加陰影的時候指定 shadow path

Appendix A: layer style property animation

Layer Style Property Animations

Appendix B: Animatable Properties

Animatable Properties

 
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved