自从提出这个问题以来已经有一段时间了,但是在四处寻找之后,我设法通过在录制过程中实时采样数据(以 1/30 秒。以 30fps 录制视频的计时器)并存储它在一个数组中。然后在后处理中,我在循环中为数组中的每个数据元素创建多个 CALayer,并在每一层上绘制该数据的可视化。
每个层都有一个 CAAnimation,它在正确的媒体时间轴上以beginTime属性淡入不透明度,这只是 1/30 秒。乘以数组索引。这个时间太短了,以至于该层立即出现在前面的层之上。如果图层背景是不透明的,它将掩盖在前一层中渲染的针头,因此看起来针头的动画与原始视频捕获非常同步。你可能需要稍微调整一下时间,但我不超过一帧。
/******** this has not been compiled but you should get the idea ************
// Before starting the AVAssetExportSession session and after the AVMutableComposition routine
CALayer* speedoBackground = [[CALayer alloc] init]; // background layer for needle layers
[speedoBackground setFrame:CGRectMake(x,y,width,height)]; // size and location
[speedoBackground setBackgroundColor:[[UIColor grayColor] CGColor]];
[speedoBackground setOpacity:0.5] // partially see through on video
// loop through the data
for (int index = 0; index < [dataArray count]; index++) {
CALayer* speedoNeedle = [[CALayer alloc] init]; // layer for needle drawing
[speedoNeedle setFrame:CGRectMake(x,y,width,height)]; // size and location
[speedoNeedle setBackgroundColor:[[UIColor redColor] CGColor]];
[speedoNeedle setOpacity:1.0]; // probably not needed
// your needle drawing routine for each data point ... e.g.
[self drawNeedleOnLayer:speedoNeedle angle:[self calculateNeedleAngle[dataArray objectAtIndex:index]]];
CABasicAnimation *needleAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
needleAnimation.fromValue = [NSNumber numberWithFloat:(float)0.0];
needleAnimation.toValue = [NSNumber numberWithFloat:(float)1.0]; // fade in
needleAnimation.additive = NO;
needleAnimation.removedOnCompletion = NO; // it obscures previous layers
needleAnimation.beginTime = index*animationDuration;
needleAnimation.duration = animationDuration -.03; // it will not animate at this speed but layer will appear immediately over the previous layer at the correct media time
needleAnimation.fillMode = kCAFillModeBoth;
[speedoNeedle addAnimation:needleAnimation forKey:nil];
[speedoBackground addSublayer:needleOverlay];
}
[parentLayer addSublayer:speedoBackground];
.
.
.
// when the AVAssetExportSession has finished, make sure you clear all the layers
parentLayer.sublayers = nil;
它是处理器和内存密集型的,因此不适用于长视频或复杂的绘图。我确信有更优雅的方法,但这有效,我希望这会有所帮助。