我有一个垂直的 1 像素 View ,我想将其移动到表示正在播放的音符的网格上。根据歌曲的 BPM(每分钟节拍数),动画应该变慢或变快。音符彼此紧挨着,宽度为 25 像素。
我现在这样做的方法是每次经过 x 个样本时将 View 向右移动 1px:
int bpm = 90;
int interval = (44100 * 60.0f / song.bpm) / 25.0f; // = 1176
// sample rate=44100 multiplied by 60 (seconds) divided by number of pixels
因此,当 BPM=90 时,我每播放 1176 个样本将 UIView 移动 1px。这工作得相当好,但如果 BPM 高于 180,就会给我带来问题。在这一点上,所播放的音乐的视野落后了,当 BPM 上升到 240 时,视野就会偏离。
我如何使用 Views 的内置动画功能来做到这一点,并根据我上面发布的计算来确定动画速度?我想在音乐开始播放后开始动画,所以我不需要逐个像素地手动移动它。
最佳答案
如果我理解正确,您想要做的是:
有两个问题需要解决:
为了获得正确的绘图性能,需要考虑两种实现:
在 OpenGL 中实现 View 的代码太多,无法作为示例发布,但这里是 Core Animation 选项的代码:
// In the UIViewController:
- (CALayer *)markerLayer
{
static NSString *uniqueName = @"com.mydomain.MarkerLayer";
for (CALayer *layer in self.view.layer.sublayers) {
if ([layer.name isEqualToString:uniqueName])
return layer;
}
CALayer *markerLayer = [CALayer layer];
markerLayer.backgroundColor = [UIColor whiteColor].CGColor;
markerLayer.name = uniqueName;
markerLayer.anchorPoint = CGPointZero;
[self.view.layer addSublayer:markerLayer];
return markerLayer;
}
- (void)startAnimationWithDuration:(NSTimeInterval)duration
{
[CATransaction begin];
[CATransaction setDisableActions:YES];
CALayer *markerLayer = [self markerLayer];
markerLayer.bounds = (CGRect){.size = {1, self.view.bounds.size.height}};
markerLayer.position = CGPointZero;
[CATransaction commit];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];
animation.fromValue = @0.0f;
animation.toValue = [NSNumber numberWithFloat:self.view.bounds.size.width];
animation.duration = duration;
[markerLayer addAnimation:animation forKey:@"audioAnimation"];
}
音频同步很大程度上取决于您的播放方式,例如使用 AVFoundation 或 Core Audio。要获得精确的同步,您需要来自音频引擎的某种回调,以告诉您现在播放的确切位置或何时开始播放。
也许在开始音频之前立即调用
startAnimationWithDuration:
就足够了,但这似乎有点脆弱,并且取决于音频框架的延迟。关于iphone - 将 UIView 动画速度与音频播放同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12046940/