19

AVComposition에 사용할 비교적 간단한 CoreAnimation을 만들려고합니다. 내 목표는 CALayer을 만들고 다양한 하위 레이어를 통해 제목을 페이드 인/페이드 아웃 한 다음 아웃 이미지를 페이드 아웃합니다. 기본적으로 슬라이드 쇼입니다. 이것은 AVAssetWriter을 사용하여 .mov로 내보내집니다.CoreAnimation - 불투명도 페이드 인 및 아웃 애니메이션이 작동하지 않음

WWDC 2011 AVEditDemo의 도움을 받아 제목과 이미지를 표시 할 수있었습니다. 문제는 그 (것)들이 동시에 모두 스크린에있다이다!

불투명도가 0.0 인 각 레이어를 만들었습니다. 나는 다음 코드를 사용하여 0.0에서 1.0로 퇴색하는 CABasicAnimation를 추가했습니다 :

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 초 있습니다. 제목과 마찬가지로 페이드 아웃 애니메이션도 정상적으로 작동합니다.

는 어떤 도움을 크게 감상 할 수있다!

건배!

편집

대답은 모두 도움이되었다, 그러나 궁극적으로 나는 단 하나의 애니메이션이 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을 당신은 비디오로의 CALayer을 수출 할 수 있었다 – gamblor87

+0

? 나는 지금 그것에 매달렸다. 조언이 있으면 제 질문에 답장하십시오. 감사! http://stackoverflow.com/questions/10285175/avfoundation-exporting-calayers-only –

답변

27

을하고, 문제는 - 한 층에서 밖으로 페이드를 포함 할 수 없습니다.내가 gamblor87과 설명으로 내 의견을 추가하여 언급 한 링크에서

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

시도 :

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

변화가없는 것처럼 보입니다. 내 편집을 참조하십시오. – gamblor87

1

내가

+0

저에게이 부동산에 대해 경고 해 주셔서 감사합니다. 다른 방법으로도 도움이되었습니다! 내 편집을 참조하십시오. – gamblor87

1

... 당신이하지 beginTime, timeOffset 찾고있는 문제의 핵심이되지 않았다 생각 CAKeyframeAnimation의 keyTimes 속성을 이해합니다. 이 질문은 모든 것을 명확하고 올바른 경로 나를 아래로 설정 : 나는이 같은 문제에 직면하고있어

What kind of value is keyTime in an CAKeyFrameAnimation?

1

차입했던 것처럼 그래서 당신은 부모 레이어에 다른 애니메이션을 추가 할 수 있습니다.

//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

사람, 너무 많은 복잡한 답변. 가장 간단한 방법은 자동 반전을 추가하는 것입니다. Voila.

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

좋은 대답 :) in func – YannickSteph

1

LenK의 대답은 나를 위해 완벽했다. 사람이 관심이 있다면, 나는 (또한 약간 페이드의 키 프레임을 변경 I주의)의 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은 UI에서도 잘 작동합니다. 이 코드는 실시간으로 쇼 애니메이션을위한 UI에서 잘 작동합니다. 그러나 은 전혀 작동하지 않습니다.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 여러 레이어의 애니메이션에는 글리치가 있습니다.

// 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]; 
    } 
} 

그리고 마지막에

AVVideoCompositionCoreAnimationTool

, 우리는 요점은 키 이름입니다 적절한 애니메이션 시퀀스를 right animation

1

를 얻을 수 있습니다. 불투명도 키를 설정해야합니다.

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

샘플 코드를 확인하십시오. 스위프트 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") 
관련 문제