我有一个垂直的 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 的内置动画功能来做到这一点,并根据我上面发布的计算来确定动画速度?我想在音乐开始播放后开始动画,所以我不需要逐个像素地手动移动它。

最佳答案

如果我理解正确,您想要做的是:

  • 绘制静态背景图像。
  • 在从左向右移动的顶部画一条垂直线。
  • 将行的 x 位置与音频播放时间同步。

  • 有两个问题需要解决:
  • 绘图性能
  • 音频同步

  • 为了获得正确的绘图性能,需要考虑两种实现:
  • 使用核心动画层和动画(比 2 更容易实现。)
  • 使用 OpenGL 绘制整个 View (可能比 1 快一点,延迟少一点。)

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

    10-12 00:27
    查看更多