Core Animaiton - 8

终于开始从CALayer 绘图的层面过渡到动画的层面了: 

Animating Layer Content

The infrastructure provided by Core Animation makes it easy to create sophisticated animations of your app’s layers, and by extension to any views that own those layers. Examples include changing the size of a layer’s frame rectangle, changing its position onscreen, applying a rotation transform, or changing its opacity. With Core Animation, initiating an animation is often as simple as just changing the property but you can also create animations and set the animation parameters explicitly.

Core Animation是基于层的结构上的,进而扩展到views that own those layers 视图上。有了Core Animation 这个神兵利器,你就可以初始化一个动画操作紧紧痛过改变属性或者明确创建一个动画并且设置相应的动画参数。



Animating Simple Changes to a Layer’s Properties

You can perform simple animations implicitly or explicitly depending on your needs. Implicit animations use the default timing and animation properties to perform an animation, whereas explicit animations require you to configure those properties yourself using an animation object. So implicit animations are perfect for situations where you want to make a change without a lot of code and the default timing works well for you.

Simple animations involve changing the properties of a layer and letting Core Animation animate those changes over time. Layers define many properties that affect the visible appearance of the layer. Changing one of these properties is a way to animate the appearance change. For example, changing the opacity of the layer from1.0 to 0.0 causes the layer to fade out and become transparent.

隐式动画操作使用默认的计时器和动画属性。而显式动画操作就要求配置相应的动画对象的属性。


Important: Although you can sometimes animate layer-backed views directly using Core Animation interfaces, doing so often requires extra steps. For more information about how how to use Core Animation in conjunction with layer-backed views, see How to Animate Layer-Backed Views.

直接在layer-backed views上使用Core Animation 的接口会折腾多余的步骤,文档提供了这方面的说明:Core Animaiton in conjunction with layer-backed views。


To trigger implicit animations, all you have to do is update the properties of your layer object. When modifying layer objects in the layer tree, your changes are reflected immediately by those objects. However, the visual appearance of the layer objects does not change immediately. What happens instead is that Core Animation uses your changes as a trigger to create and schedule one or more implicit animations for execution. Thus, making 

这里说明了一点挺奇怪的,为了触发隐含的动画操作,所有你将要做的事情是更新层对象的属性,当在层结构树上修改层对象,你的修改会马上映射到这些对象。然而,图层对象的并不会马上改变,取而代之的是Core Animation使用了你的改变作为一个触发器来创建一个schedule一个或多个隐式动画来执行,因此,执行:

theLayer.opacity = 0.0;


To make the same change explicitly using an animation object, create aCABasicAnimation object and use that object to configure the animation parameters. You can set the start and end values for the animation, change the duration, or change any other animation parameters before adding the animation to a layer. Listing 3-2 shows how to fade out a layer using an animation object. When creating the object, you specify the key path for the property you want to animate and then set your animation parameters. To execute the animation, you use the addAnimation:forKey: method to add it to the layers you want to animate.

相对来说,显式动画的几点区别: 1. 创建animation objects : CABasicAnimation 对象  2. 配置animation parameters 动画参数 (一般是初始值和结束值,修改持久时间,或者其他动画相关参数)

同时还要注意一点:specify the key path for property , 使用 addAnimation:forKey:方法来增加所要执行动画的图层。

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;

官方文档写得太简单了,这里我提供一个例子:

自定义一个图层类LBLayer.h

#import "LBLayer.h"

@implementation LBLayer

- (void)drawInContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 135.0/255.0, 232.0/255.0, 84.0/255.0, 1 );
    CGContextSetRGBStrokeColor(ctx, 135.0/255.0, 232.0/255.0, 84.0/255.0, 1);
    CGContextMoveToPoint(ctx, 94.5, 33.5);
    
    CGContextAddLineToPoint(ctx,104.02, 47.39);
    CGContextAddLineToPoint(ctx,120.18, 52.16);
    CGContextAddLineToPoint(ctx,109.91, 65.51);
    CGContextAddLineToPoint(ctx,110.37, 82.34);
    CGContextAddLineToPoint(ctx,94.5, 76.7);
    CGContextAddLineToPoint(ctx,78.63, 82.34);
    CGContextAddLineToPoint(ctx,79.09, 65.51);
    CGContextAddLineToPoint(ctx,68.82, 52.16);
    CGContextAddLineToPoint(ctx,84.98, 47.39);
    CGContextClosePath(ctx);
    
    CGContextDrawPath(ctx, kCGPathFillStroke);
}

@end

自定义一个UIView类并且使用了上面的自定义类:

#import "LBView.h"
#import "LBLayer.h"

@implementation LBView

- (instancetype)initWithFrame:(CGRect)frame
{    
    if (self = [super initWithFrame:frame])
    {
        LBLayer* layer = [[LBLayer alloc] init];
        layer.bounds = CGRectMake(0, 0, 185, 185);
        layer.position = CGPointMake(160, 284);
        layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
        
        [layer setNeedsDisplay];
        
        [self.layer addSublayer:layer];
    }
    
    return self;
}

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{

    [super drawLayer:layer inContext:ctx];
}

@end

在一个视图控制器上输出结果:

#import "LBView.h"
#import "LBLayerPractiseController.h"

@interface LBLayerPractiseController ()

@end

@implementation LBLayerPractiseController


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    LBView* view = [[LBView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    view.backgroundColor=[UIColor colorWithRed:249.0/255.0 green:249.0/255.0 blue:249.0/255.0 alpha:1];
    
    
    [self.view addSubview:view];
}

@end

结果如下:


将上图的透明度用动画设置:(注意:应该在图层出现的地方添加,所以我在自定义图层的时候添加上了,也可以在别的地方添加,这里因为测试所以图个方便)

用implicitly方式,用隐式的方法添加:

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        LBLayer* layer = [[LBLayer alloc] init];
        layer.bounds = CGRectMake(0, 0, 185, 185);
        layer.position = CGPointMake(160, 284);
        layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
        
        layer.opacity = 0.0;

        [layer setNeedsDisplay];
        
        [self.layer addSublayer:layer];
    }
    
    return self;
}
结果是空白,很显然的,按照文档所说的就是直接产生了变化但是没有外面的可视的变化: your changes are reflected immediately by those objects. However, the visual appearance of the layer objects does not change immediately

用explicitly方式,用显式的方法添加:

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        LBLayer* layer = [[LBLayer alloc] init];
        layer.bounds = CGRectMake(0, 0, 185, 185);
        layer.position = CGPointMake(160, 284);
        layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
        
        CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
        fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
        fadeAnim.toValue   = [NSNumber numberWithFloat:0.0];
        fadeAnim.duration  = 2.0;
        [layer addAnimation:fadeAnim forKey:@"opacity"];
        
        [layer setNeedsDisplay];
        
        [self.layer addSublayer:layer];
    }
    
    return self;
}
这个就是我们期待的,从完全显示到完全透明,但是最后为什么一下子又变回完全显示呢?

官方文档在后面给了我们解释:

Unlike an implicit animation, which updates the layer object’s data value, an explicit animation does not modify the data in the layer tree. Explicit animations only produce the animations. At the end of the animation, Core Animation removes the animation object from the layer and redraws the layer using its current data values. If you want the changes from an explicit animation to be permanent, you must also update the layer’s property as shown in the preceding example.

并不像隐式动画操作,能够更新这个图层对象的数据值,一个显式动画操作并不修改图层树的数据。显式动画操作紧紧执行动画,在动画的最后,Core Animation移除了图层上的动画对象并且重绘了图层使用当前的数据值,如果你希望一个显式动画操作的修改值是永久的,你必须更新图层属性如例子所示:

就是非常简单,在显式动画操作后中添加一行:

        layer.opacity = 0.0;
这样就同时保证了动画和数值了!

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. If you change multiple properties, or if you add multiple animation objects to a layer, all of those property changes are animated at the same time. For example, you can fade a layer while moving it offscreen by configuring both animations at the same time. However, you can also configure animation objects to start at a particular time. For more information about modifying animation timing, see Customizing the Timing of an Animation.

隐式和显式动画操作尝尝时在当前run loop cycle(run loop 循环)结束后才开始执行的,而且当前的线程必须拥有一个run loop从而保证动画操作会被执行。如果你修改了多个属性,或者如果你添加了多个动画操作对象给一个图层,所有属性的修改会被同时动画操作。例如,你可以将一个图层渐变同时将它移出屏幕之外。然而,你也可以配置一个动画对象在一个特殊的时间点开始,详情参看:Customizing the Timing of an Animation.





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值