19

Я пытаюсь создать довольно простой CoreAnimation для использования в AVComposition. Моя цель - создать CALayer, который через различные подслои стирает заголовок и выходит, а затем исчезает в образах. Слайд-шоу, в основном. Это экспортируется в .mov, используя AVAssetWriter.CoreAnimation - Непрозрачность Fade In и Out Анимация не работает

С помощью WWE 2011 AVEditDemo я смог получить заголовок и изображения. Проблема в том, что они все на экране одновременно!

Я создал каждый слой с непрозрачностью 0.0. Я потом добавил CABasicAnimation исчезать их от 0,0 до 1,0, используя следующий код:

CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
fadeInAnimation.fromValue = [NSNumber numberWithFloat:0.0]; 
fadeInAnimation.toValue = [NSNumber numberWithFloat:1.0]; 
fadeInAnimation.additive = NO; 
fadeInAnimation.removedOnCompletion = YES; 
fadeInAnimation.beginTime = 1.0; 
fadeInAnimation.duration = 1.0; 
fadeInAnimation.fillMode = kCAFillModeForwards; 
[titleLayer addAnimation:fadeInAnimation forKey:nil]; 

Проблема, как представляется, являются собственностью «BeginTime». «1.0» означает задержку, поэтому он начинается через 1 секунду после начала анимации. Тем не менее, он появляется на экране сразу. Анимация затухания

Реверс этого кода, для постепенного исчезновения, просто изменяет fromValue на 1.0 и toValue на 0.0. Он имеет время начала 4.0 и работает отлично.

Я использую следующие для создания animatedTitleLayer:

CATextLayer *titleLayer = [CATextLayer layer]; 
titleLayer.string =self.album.title; 
titleLayer.font = @"Helvetica"; 
titleLayer.fontSize = videoSize.height/6; 
titleLayer.alignmentMode = kCAAlignmentCenter; 
titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height/6); 
titleLayer.foregroundColor = [[UIColor redColor]CGColor]; 
titleLayer.opacity = 0.0; 

перепыла изображения в анимации есть BeginTime 5 секунд друг от друга. Как и название, их угасающие анимации отлично работают.

Любая помощь была бы принята с благодарностью!

Cheers!

EDIT

ответы были полезны, но в конце концов я обнаружил, что только одна анимация может быть добавлен к CALayer. Активизировалась анимация с постепенным исчезновением, поскольку она была последней.

Затем я попробовал CAAnimationGroup, но это не сработало, поскольку я изменял один и тот же путь значений ключа.

Так что я понял, что CAKeyframeAnimation является лучшим для этого. Только у меня есть с этим трудности! Код теперь исчезает в порядке, но он не исчезает. Я пробовал различные fillMode, менял продолжительность и т. Д. Не могу заставить его работать!

Вот мой код:

CAKeyframeAnimation *fadeInAndOut = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; 
    fadeInAndOut.duration = 5.0; 
    fadeInAndOut.autoreverses = NO; 
    fadeInAndOut.keyTimes = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0], 
                  [NSNumber numberWithFloat:1.0], 
                [NSNumber numberWithFloat:4.0], 
                [NSNumber numberWithFloat:5.0], nil]; 

    fadeInAndOut.values = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0], 
                [NSNumber numberWithFloat:1.0], 
                [NSNumber numberWithFloat:1.0], 
                [NSNumber numberWithFloat:0.0], nil]; 
    fadeInAndOut.beginTime = 1.0; 
    fadeInAndOut.removedOnCompletion = NO; 
    fadeInAndOut.fillMode = kCAFillModeBoth; 
    [titleLayer addAnimation:fadeInAndOut forKey:nil]; 
+0

так вы пытаетесь заблаговременно располагать и настраивать слои, или вы можете добавить их в качестве перехода по слайдам? – nielsbot

+0

Я позиционирую и настраиваю заранее. Я понял это благодаря этому сообщению: http://stackoverflow.com/questions/2184803/what-kind-of-value-is-keytime-in-an-cakeyframeanimation – gamblor87

+0

Вы смогли экспортировать CALayer в видео? Я застрял на этом сейчас. Если у вас есть какие-либо советы, ответьте на мой вопрос. Благодаря! http://stackoverflow.com/questions/10285175/avfoundation-exporting-calayers-only –

ответ

27

Я сталкивался с таким же вопросом и проблема - один слой не может содержать увядает и выход. Таким образом, вы можете добавить другую анимацию родительского слоя, как я сделал

CALayer *parentLayer = [CALayer layer]; 
CALayer *animtingLayer = [CALayer layer]; 

//FADE IN 
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.beginTime = CMTimeGetSeconds(img.startTime); 
     animation.duration = CMTimeGetSeconds(_timeline.transitionDuration); 
     animation.fromValue = [NSNumber numberWithFloat:0.0f]; 
     animation.toValue = [NSNumber numberWithFloat:1.0f]; 
     animation.removedOnCompletion = NO; 
     animation.fillMode = kCAFillModeBoth; 
     animation.additive = NO; 
     [parentLayer addAnimation:animation forKey:@"opacityIN"]; 

//FADE OUT 
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.beginTime = CMTimeGetSeconds(CMTimeAdd(img.passTimeRange.start, img.passTimeRange.duration)); 
     animation.duration = CMTimeGetSeconds(_timeline.transitionDuration); 
     animation.fromValue = [NSNumber numberWithFloat:1.0f]; 
     animation.toValue = [NSNumber numberWithFloat:0.0f]; 
     animation.removedOnCompletion = NO; 
     animation.fillMode = kCAFillModeBoth; 
     animation.additive = NO; 
     [animtingLayer addAnimation:animation forKey:@"opacityOUT"]; 

    [parentLayer addSublayer:animtingLayer]; 
+1

Я бы никогда не подумал об этом. Спасибо @comonitos –

+0

@DavidJohnSmith рад помочь! – comonitos

+0

Возможно, это связано с обновлением iOS 7 SDK 2013-14 или чем-то, что я сделал по-другому, но в настоящее время возможно добавление ** нескольких ** анимаций в один ** слой **, что делает ненужным использование дополнительного слоя @comonitos – petershine

1

Try:

fadeInAnimation.beginTime = CACurrentMediaTime()+1.0; 
+0

Кажется, не имеет значения. См. Мое редактирование. – gamblor87

1

Я думаю, что вы ищете timeOffset, не beginTime ...

+0

Спасибо, что предупредили меня об этом. Помог другим способом! См. Мое редактирование. – gamblor87

1

Заимствования по ссылке, упомянутой gamblor87 и добавив свои комментарии в качестве объяснения.

//create a fadeInOut CAKeyframeAnimation on opacticy 
CAKeyframeAnimation *fadeInAndOut = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; 

//set duration 
fadeInAndOut.duration = 5.0; 

//autoreverses defaults to NO so we don't need this. 
//fadeInAndOut.autoreverses = NO; 

//keyTimes are time points on duration timeline as a fraction of animation duration (here 5 seconds). 
fadeInAndOut.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], 
                [NSNumber numberWithFloat:0.20], 
                [NSNumber numberWithFloat:0.80], 
                [NSNumber numberWithFloat:1.0], nil]; 


//set opacity values at various points during the 5second animation 
fadeInAndOut.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],//opacity 0 at 0s (corresponds to keyTime = 0s/5s) 
               [NSNumber numberWithFloat:1.0],//opacity 1 at 1s (corresponds to keyTime = 1s/5s) 
               [NSNumber numberWithFloat:1.0],//opacity 1 upto 4s (corresponds to keyTime = 4s/5s) 
               [NSNumber numberWithFloat:0.0],//opacity 0 at 5s (corresponds to keyTime = 5s/5s) 
nil]; 

//delay in start of animation. What we are essentially saying is to start the 5second animation after 1second. 
fadeInAndOut.beginTime = 1.0; 

//don't remove the animation on completion. 
fadeInAndOut.removedOnCompletion = NO; 

//fill mode. In most cases we won't need this. 
fadeInAndOut.fillMode = kCAFillModeBoth; 

//add the animation to layer 
[titleLayer addAnimation:fadeInAndOut forKey:nil]; 
+1

fadeInAndOut.beginTime = 1.0 не работает, вам нужно использовать CACurrentMediaTime() + 1; – Jay

23

Человек, так много сложных ответов. Самый простой способ - просто добавить autoreverse. Вуаля.

CABasicAnimation *fadeInAndOut = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
fadeInAndOut.duration = 5.0; 
fadeInAndOut.autoreverses = YES; 
fadeInAndOut.fromValue = [NSNumber numberWithFloat:0.0]; 
fadeInAndOut.toValue = [NSNumber numberWithFloat:1.0]; 
fadeInAndOut.repeatCount = HUGE_VALF; 
fadeInAndOut.fillMode = kCAFillModeBoth; 
[titleLayer addAnimation:fadeInAndOut forKey:@"myanimation"]; 
+2

Это решение начинает исчезать, как только завершение замирания. Я предполагаю, что OP хочет, чтобы название затухало, осталось немного видимым, а затем исчезло. – oskare

+1

Действительно лучший ответ. Я бы добавил, что для тех, кто борется, вы также можете добавить [yourView setWantsLayer: YES]; прежде чем получить слой вашего представления. По умолчанию представления не имеют слоев. – Borzh

2

Это работает для меня:

let fadeAnimation = CAKeyframeAnimation(keyPath:"opacity") 
fadeAnimation.beginTime = AVCoreAnimationBeginTimeAtZero + start 
fadeAnimation.duration = duration 
fadeAnimation.keyTimes = [0, 1/8.0, 5/8.0, 1] 
fadeAnimation.values = [0.0, 1.0, 1.0, 0.0] 
fadeAnimation.removedOnCompletion = false 
fadeAnimation.fillMode = kCAFillModeForwards 
layer.addAnimation(fadeAnimation, forKey:"animateOpacity") 
layer.opacity = 0.0 
+0

Хороший ответ :) в func – YannickSteph

1

LenK «s ответ работал отлично для меня. Если кому-то интересно, я снова написал для Obj-C (обратите внимание, я также немного изменил ключевые кадры на замирания в):

CAKeyframeAnimation *fadeInAndOutAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; 
fadeInAndOutAnimation.beginTime = CACurrentMediaTime() + beginTime; 
fadeInAndOutAnimation.duration = duration; 
fadeInAndOutAnimation.keyTimes = @[@0.0, @(2.0/8.0), @(5.0/8.0), @1.0]; 
fadeInAndOutAnimation.values = @[@0.0, @1.0, @1.0, @0.0]; 
fadeInAndOutAnimation.removedOnCompletion = false; 
fadeInAndOutAnimation.fillMode = kCAFillModeForwards; 
+0

Это сработало для меня, но вам нужно добавить еще одну строку: 'fadeInAndOutAnimation.repeatCount = HUGE_VALF;'. В противном случае вид исчезает один раз и больше не появляется. – rmaddy

1

Альтернативный способ - использование CAAnimationGroup. CAKeyframeAnimation также отлично подходит для пользовательского интерфейса. Этот код отлично работает в пользовательском интерфейсе для анимации шоу в реальном времени. Но не будет работать вообще в AVVideoCompositionCoreAnimationTool - прокрутите вниз, если вам это нужно. Это не готовый код для копирования-вставки, но вы можете получить эту идею. Кроме того, вы можете добавить аддитивную анимацию к группе:

for (HKAnimatedLayer *animLayer in layersList) { 

    overlayLayer = [CALayer layer]; 
    [overlayLayer setContents:(id)[animLayer.image CGImage]]; 
    overlayLayer.frame = CGRectMake(0, 0, size.width, size.height); 
    [overlayLayer setMasksToBounds:YES]; 

    NSMutableArray *animations = [NSMutableArray array]; 
    // Step 1 
    { 
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.toValue = @(0); 
     animation.duration = kLayerFadeDuration; 
     animation.beginTime = kMovieDuration/5; 
     animation.fillMode = kCAFillModeForwards; 
     [animations addObject:animation]; 
    } 
    { 
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.toValue = @(1.0); 
     animation.duration = kLayerFadeDuration; 
     animation.beginTime = kMovieDuration*2/3; 
     animation.fillMode = kCAFillModeForwards; 
     [animations addObject:animation]; 
    } 

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 
    animationGroup.animations = animations; 
    animationGroup.duration = kMovieDuration; 
    animationGroup.fillMode = kCAFillModeForwards; 
    animationGroup.removedOnCompletion = YES; 

    [overlayLayer addAnimation:animationGroup forKey:nil]; 

    [parentLayer addSublayer:overlayLayer]; 
} 

Вот небольшой заметке о анимации на слоях для AVVideoCompositionCoreAnimationTool. Вы можете увидеть соответствующее изображение gif (заголовки должны появляться и исчезать один за другим). Для решения этой проблемы я использую 2 отдельных CALayer, потому что по какой-то причине на одном уровне 2 opaque анимации на нескольких слоях сбиты.

AVVideoCompositionCoreAnimationTool

// set up the parent layer 
CALayer *parentLayer = [CALayer layer]; 
parentLayer.frame = CGRectMake(0, 0, size.width, size.height); 

// one layer for one animation 
CALayer *overlayLayer, *barrierLayer; 
CABasicAnimation *animation; 

for (HKAnimatedLayer *animLayer in layersList) { 
    overlayLayer = [CALayer layer]; 
    overlayLayer.contents = (id)[animLayer.image CGImage]; 
    overlayLayer.frame = CGRectMake(0, 0, size.width, size.height); 
    overlayLayer.masksToBounds = YES; 

    // layer with appear animation 
    if (animLayer.fromTime != 0 && (animLayer.fromTime - kLayerFadeDuration)>0) { 
     overlayLayer.opacity = 0.0; 

     animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.fromValue = @(0); 
     animation.toValue = @(1); 
     animation.additive = NO; 
     animation.removedOnCompletion = NO; 
     animation.beginTime = animLayer.fromTime - kLayerFadeDuration; 
     animation.duration = kLayerFadeDuration; 
     animation.fillMode = kCAFillModeForwards; 

     [overlayLayer addAnimation:animation forKey:@"fadeIn"]; 
    } 

    if (animLayer.toTime == kMovieDuration) { 
     [parentLayer addSublayer:overlayLayer]; 
    } else { // layer with dissappear animation 
     barrierLayer = [CALayer layer]; 
     barrierLayer.frame = CGRectMake(0, 0, size.width, size.height); 
     barrierLayer.masksToBounds = YES; 
     [barrierLayer addSublayer:overlayLayer]; 

     animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.fromValue = @(1); 
     animation.toValue = @(0); 
     animation.additive = NO; 
     animation.removedOnCompletion = NO; 
     animation.beginTime = animLayer.toTime; 
     animation.duration = kLayerFadeDuration; 
     animation.fillMode = kCAFillModeForwards; 

     [overlayLayer addAnimation:animation forKey:@"fadeOut"]; 
     [parentLayer addSublayer:barrierLayer]; 
    } 
} 

И в конце концов, мы можем получить правильную последовательность анимационного right animation

1

Дело имя ключа. Вы должны установить непрозрачный ключ.

layer.add(animation, forKey: nil)   // Not Working 
layer.add(animation, forKey: "opacity") // Working 

Проверьте код образца. Я протестировал в Swift 4

let animation     = CAKeyframeAnimation() 
    animation.duration    = 1.53 
    animation.autoreverses   = false 
    animation.keyTimes    = [0, 0.51, 0.85, 1.0] 
    animation.values    = [0.5, 0.5, 1.0, 0.5] 
    animation.beginTime    = 0 
    animation.isRemovedOnCompletion = false 
    animation.fillMode    = kCAFillModeBoth 
    animation.repeatCount   = .greatestFiniteMagnitude 
    layer.add(animation, forKey: "opacity")