问题
Okay, this one has me completed stumped. I'm happy to post other code if you need it but I think this is enough. I cannot for the life of me figure out why things are going wrong. I'm adding CALayers, which contain images, to a composition using AVVideoCompositionCoreAnimationTool. I create an NSArray of all the annotations (see interface below) I want to add and then add them to the animation layer with an enumerator. No matter how many, as far as I can tell, annotations are in the array, the only ones that end up in the outputted video are the ones added by the last loop. Can someone spot what I'm missing?
Here's the interface for the annotations
@interface Annotation : NSObject// <NSCoding>
@property float time;
@property AnnotationType type;
@property CALayer *startLayer;
@property CALayer *typeLayer;
@property CALayer *detailLayer;
+ (Annotation *)annotationAtTime:(float)time ofType:(AnnotationType)type;
- (NSString *)annotationString;
@end
And here's the message that creates the video composition with the animation.
- (AVMutableVideoComposition *)createCompositionForMovie:(AVAsset *)movie fromAnnotations:(NSArray *)annotations {
AVMutableVideoComposition *videoComposition = nil;
if (annotations){
//CALayer *imageLayer = [self layerOfImageNamed:@"Ring.png"];
//imageLayer.opacity = 0.0;
//[imageLayer setMasksToBounds:YES];
Annotation *ann;
NSEnumerator *enumerator = [annotations objectEnumerator];
CALayer *animationLayer = [CALayer layer];
animationLayer.frame = CGRectMake(0, 0, movie.naturalSize.width, movie.naturalSize.height);
CALayer *videoLayer = [CALayer layer];
videoLayer.frame = CGRectMake(0, 0, movie.naturalSize.width, movie.naturalSize.height);
[animationLayer addSublayer:videoLayer];
// TODO: Consider amalgamating this message and scaleVideoTrackTime:fromAnnotations
// Single loop instead of two and sharing of othe offset variables
while (ann = (Annotation *)[enumerator nextObject]) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 3; // TODO: Three seconds is the currently hard-coded display length for an annotation, should this be a configurable option after the demo?
animation.repeatCount = 0;
animation.autoreverses = NO;
animation.removedOnCompletion = NO;
animation.fromValue = [NSNumber numberWithFloat:1.0];
animation.toValue = [NSNumber numberWithFloat:1.0];
animation.beginTime = time;
// animation.beginTime = AVCoreAnimationBeginTimeAtZero;
ann.startLayer.opacity = 0.0;
ann.startLayer.masksToBounds = YES;
[ann.startLayer addAnimation:animation forKey:@"animateOpacity"];
[animationLayer addSublayer:ann.startLayer];
ann.typeLayer.opacity = 0.0;
ann.typeLayer.masksToBounds = YES;
[ann.typeLayer addAnimation:animation forKey:@"animateOpacity"];
[animationLayer addSublayer:ann.typeLayer];
ann.detailLayer.opacity = 0.0;
ann.detailLayer.masksToBounds = YES;
[ann.detailLayer addAnimation:animation forKey:@"animateOpacity"];
[animationLayer addSublayer:ann.detailLayer];
}
videoComposition = [AVMutableVideoComposition videoCompositionWithPropertiesOfAsset:movie];
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:animationLayer];
}
return videoComposition;
}
I want to stress that the video outputs correctly and I do get the layers appearing at the right time, just not ALL the layers. Very confused and would greatly appreciate your help.
回答1:
So I was fiddling around trying to figure out what might have caused this and it turns out that it was caused by the layers hidden property being set to YES. By setting it to NO, all the layers appear but then they never went away. So I had to change the animation's autoreverses property to YES and halve the duration.
So I changed the code to this:
while (ann = (Annotation *)[enumerator nextObject]){
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 1.5; // TODO: Three seconds is the currently hard-coded display length for an annotation, should this be a configurable option after the demo?
animation.repeatCount = 0;
animation.autoreverses = YES; // This causes the animation to run forwards then backwards, thus doubling the duration, that's why a 3-second period is using 1.5 as duration
animation.removedOnCompletion = NO;
animation.fromValue = [NSNumber numberWithFloat:1.0];
animation.toValue = [NSNumber numberWithFloat:1.0];
animation.beginTime = time;
// animation.beginTime = AVCoreAnimationBeginTimeAtZero;
ann.startLayer.hidden = NO;
ann.startLayer.opacity = 0.0;
ann.startLayer.masksToBounds = YES;
[ann.startLayer addAnimation:animation forKey:@"animateOpacity"];
[animationLayer addSublayer:ann.startLayer];
ann.typeLayer.hidden = NO;
ann.typeLayer.opacity = 0.0;
ann.typeLayer.masksToBounds = YES;
[ann.typeLayer addAnimation:animation forKey:@"animateOpacity"];
[animationLayer addSublayer:ann.typeLayer];
ann.detailLayer.hidden = NO;
ann.detailLayer.opacity = 0.0;
ann.detailLayer.masksToBounds = YES;
[ann.detailLayer addAnimation:animation forKey:@"animateOpacity"];
[animationLayer addSublayer:ann.detailLayer];
}
来源:https://stackoverflow.com/questions/29760283/avvideocompositioncoreanimationtool-not-adding-all-calayers