AVFoundation - 动画图层内容

1. CoreAnimation 在不需要使用OpenGL或OPenGL ES框架的前提下就可以很容易创建高性能, 基于GPU的动画效果. CoreAnimation框架提供的有硬件加速视频渲染效果. 从高层次角度看, Core Animation包含两类对象: Layers和Animations.

2. Layers 图层对象有CALayer类定义, 并用于管理屏幕中可视化内容的元素. 这里所说的内容一般都是图片或Bezier路径, 不过图层本身具有可被设置的可视化特征. 比如他的颜色, 透明度和角半径. 除了CALayer框架还定义了很多实用的子类, 比如用于渲染贴图内容的CATextLayer类和用于渲染Beizier路径的CAShapeLyer类. 这两个类在创建动画叠加效果时都非常重要.

3. Animations 动画对象是抽象类CAAnimation的实例, 定义所有动画类型共有的一些核心动画行为.该框架定义了CAAnimation的许多具体子类. 最常用的就是CABasicAnimation和CAKeyFrameAniation. 这些类将动画状态变为单独的图层属性, 以便创建简单的和复杂的动画效果. CABasicAnimation 可以让你创建简单的单关键帧动画, 意味着在一段时间内将属性状态以动画方式由一种状态变为另一种状态. 这个类实现简单动画时非常实用. 比如动态调整图层的尺寸, 位置和背景色. CAKeyFrameAnimation用于实现更高级的功能, 它对动画中的关键帧有着更多的控制. 比如当一个图层沿着Bezier路径动态显示, 可以用到关键帧动画来指定具体的时间和节奏.

CALayer *parentLayer = //parent layer

UIImage *image = [UIImage imageNamed:@"image.png"];

CALayer *imageLayer = [CALayer layer];

imageLayer.contents = (id)image.CGImage

imageLayer.contentScale = [UIScreen mainScreen].scale;

CGFloat midX = CGRectGetMidX(parentLayer.bounds);

CGFloat midY = CGRectGEtMidY(parentLayer.bounds);

imageLayer.bounds = CGRectMake(0, 0, image.size.width, image.size.height);

imageLayer.position = CGPointMake(midX, midY);

[parentLayer addSublayer:imageLayer];

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

rotationAnimation.toValue = @(2 * M_PI);

roationAnimation.duration = 3.0f;

rotationAnimation.repeatCount = HUGE_VALF;

[imageLayer addAnimation:rotationAnimation forKey:@"rotateAnimation"];

4. 在AVFoundation中使用Core Animation, 使用Core Animation为视频应用程序创建叠加效果的方法同使用它在iOS和OS X平台创建实时动画效果的方法几乎一样. 最大的区别在于运行动画的时间模型. 当创建实时动画时, CAAnimation实例从系统主机获取执行时间.

5. AVSynchronizedLayer播放, AVFoundation提供了一个专门的CALayer的子类AVSynchronizedLayer, 用于与给定的AVPlayerItem实例同步时间, 这个图层本身不展示任何内容. 仅用来与图层子树协同时间. 这样所在的继承关系中附属于改图层的动画都可以从激活的AVPlayerItem实例中获取相应的执行时间. 通常使用AVSynchronizedLayer时会将其整合到播放器视图的图层继承关系中. 同步图层直接呈现在视频图层之上. 这样就可以添加动画标题, 水印或下沿字幕到播放器视频中, 并与播放器栏行为保持完美同步.

6. 使用AVVideoCompositionCoreAnimationTool导出, 要将Core Animation图层和动画整合到导出视频中, 需要使用AVVideoCompositionCoreAnimationTool类, AVVideoComposition使用这个类将Core Animation效果作为视频组合后期处理阶段纳入.

7. Core Animation框架的默认行为是执行动画并在动画行为完成后进行处理, 通常这些行为就是我们希望在按理中使用的, 因为时间一旦过去就没法返回了. 不过对于视频动画就会有问题. 所以需要设置动画的removedOnCompletion属性来NO来禁用这一行为. 如果不这样做, 则动画效果是一次性的. 如果用户重新播放视频或在时间轴上移动戳插条也不会再次看到动画. 动画的beginTime属性被设置为0.0的话是不会看到动画效果的. Core Animation将值为0.0的beginTime对象转换为CACurrentMediaTime(), 这是当前主机时间, 同影片时间轴中的有效时间没有关系. 如果希望在影片开头加入动画, 将动画的beginTime属性设置成AVCoreAnimationBeginTimeAtZero常量.

8. 添加动画标题, 在Core Animation中使用AVComposition的一个挑战就是协调不同的概念和时间模型. 在使用AVComposition时, 考虑的是轨道以及CMTime和CMTimeRange值, Core Animation没有轨道的概念并使用浮点型数值来表示时间. 在一个简单场景中我们可以使用Core Animation自己的概念, 不过当需要创建一个更复杂的案例时, 最好在两个框架之间定义一个通用的抽象概念来使创建组合资源和动画时具有标准化的模型. 

9. 创建一个简单的THTimeLineItem对象THTittleItem, 用于将动画标题添加到项目中.

@interface THTimtleItem: THTimelineItem

+ (instancetype)titleItemWithText:(NSString *)text image:(UIImage *)image;

- (instancetype)initWithText:(NSString *)text image:(UIImage *)image;

@property (copy, nonatomic) NSString *identifier;

@property (nonatomic) BOOL animateImage;

@property (nonatomic) BOOL useLargeFont;

- (CALayer *)buildLayer;

@end

@interface THTitleItem ()

@property (nonatomic, copy ) NSString *text;

@property (nonatomic, strong) UIImage *image;

@property (nonatomic) CGRect bounds;

@end

@implementation THTitleItem 

+ (instancetype)titleItemWithText:(NSString *)text image:(UIImage *)image {

    return [[self alloc] initWithText:text image:image];

}

- (instancetype)initWithText:(NSString *)text image:(UIImage *)image {

    self = [super init];

    if (self) {

        _text = text;

        _image = image;

        _bounds = TH720pVideoRect;

    }

    return self;

}

- (CALayer *)buildLayer {

    CALayer *parentLayer = [CALayer layer];

    parentLayer.frame = self.bounds;

    parentLayer.opacity = 0.0f;

    CALayer *imageLayer = [self makeImageLayer];

    [parentLayer addSubLayer:imageLayer];

    CALayer *textLayer = [self makeTextLayer];

    [parentLayer addSublayer:textLayer];

    return parentLayer;

}

- (CALayer *)makeImageLayer {

    CGSize imageSize = self.image.size;

    CALayer *layer = [CALayer layer];

    layer.contents = (id)self.image.CGImage;

    layer.allowsEdgeAntialiasing = YES;

    layer.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);

    layer.position = CGPointMake(CGRectGetMidX(self.bounds) - 20, 270);

    return layer;

}

- (CALayer *)makeTextLayer {

    CGFloat fontSize = self.userLargeFont ? 64 : 54;

    UIFont *font = [UIFont fontWithName:@"GillSans-Bold" size:fontSize];

    NSDictionary *attrs = @{NSFontAttributeName:font, NSForegroundColorAttributeName: (id)[UIColor whiteColor].CGColor};

    NSAttributeString *string = [[NSAttributedString alloc] initWithString:self.text attributes:attrs];

    CGSize textSize = [self.text sizeWithAttributes:attrs];

    CATextLayer *layer = [CATextLayer layer];    

    layer.string = string;

    layer.bounds = CGRectMake(0, 0, textSize.width, textSize.height);

    layer.position = CGPointMake(CGRectGetMidX(self.bounds), 470.0);

    layer.backgroundColor = [UIColor clearColor].CGColor;

    return layer;

}

@end

10. 创建淡入淡出动画效果

@implementation THTitleItme

...

- (CALayer *)buildLayer {

    CALayer *parentLayer = [CALayer layer];

    parentLayer.frame = self.bounds;

    parentLayer.opacity = 0.0f;

    CALayer *imageLayer = [self makeImageLayer];

    [parentLayer addSubLayer:imageLayer];

    CALayer *textLayer = [self makeTextLayer];

    [parentLayer addSublayer:textLayer];

    // --- build and attach animations ---

    CAAnimation *fadeInFadeOutAnimation = [self makeFadeInFadeOutAnimation];

    [parentLayer addAnimation:fadeInFadeOutAnimation forKey:nil];

    return parentLayer;

}

- (void)makeFadeInFadeOutAnimation {

    CAKeyframeAnimation *animation = [CAKeyAnimation animationWithKeyPath:@"opacity"];

    animation.values = @[@0, @1, @1, @0];

    animation.keyTimes = @[@0, @0.2, @0.8, @1];

    animation.removeOnCompletion = NO;

    return animation;

}

@end

11. 为标题图片添加动画

- (CALayer *)buildLayer {

    CALayer *parentLayer = [CALayer layer];

    parentLayer.frame = self.bounds;

    parentLayer.opacity = 0;

    CALayer *imageLayer = [self makeImageLayer];

    [parentLayer addSubLayer:imageLayer];

    CALayer *textLayer = [self makeTextLayer];

    [parentLayer addSubLayer:textLayer];

    CAAnimation *fadeInFadeOutAnimation = [self makeFadeInFadeOutAnimation];

    [parentLayer addAnimation:fadeInFadeOutAnimation forKey:nil];

    if (self.animateImage) {

        //应用一个3d绕y轴旋转动画, 必须设置父视图的透视变化

        parentLayer.sublayerTransform = THMakePerspectiveTransform(1000);

        CAAnimation *spinAnimation = [self make3DSpinAnimation];      

        NSTimeInterval offset = spinAnimation.beginTime + spinAnimation.duration - 0.5;

        CAAnimation *popAnimation = [self makePopAnimationWithTimingOffset:offset];

    [imageLayer addAnimation:spinAnimation forKey:nil]; 

    [imageLayer addAnimation:popAnimation forKey:nil];

    }

    return parentLayer;    

}

static CATransform3D THMakePerspectiveTransform(CGFloat eyePosition) {

    CATransform3d transform = CGTransform3DIdentify;

    transform.m34 = -1.0 / eyePosition;

    return transform;

}

- (CAAnimation *)make3DSpinAnimation {

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath@"transform.rotation.y"];

    animation.toValue = @{(4 * M_PI) * -1};    

    animation.beginTime = CMTimeGetSeconds(self.startTimeInTimeline) + 0.2;

    animation.duration = CGTimeGetSeconds(self.timeRange.duratoin) * 0.4;

    animation.removeOnCompletion = NO;

    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    return animation;

}

- (CAAnimation *)makePopAnimationWithTimingOffset:(NSTimeInterval)offset {

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

    animation.toValue = @1.3;

    animation.beginTime = offset;

    animation.duration = 0.35;

    animation.autoreverses = YES;    

    animation.removeOnCompletion = NO;

    animation.timingFunction = [CADediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    return animation;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容

  • 1 CALayer IOS SDK详解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi阅读 5,142评论 3 23
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,109评论 5 13
  • 如果想让事情变得顺利,只有靠自己--夏尔·纪尧姆 上一章介绍了隐式动画的概念。隐式动画是在iOS平台创建动态用户界...
    夜空下最亮的亮点阅读 1,937评论 0 1
  • 显式动画 显式动画,它能够对一些属性做指定的自定义动画,或者创建非线性动画,比如沿着任意一条曲线移动。 属性动画 ...
    清风沐沐阅读 1,930评论 1 5
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,089评论 1 23