在NSView中绘制波形

3
我需要在NSView中绘制波形图(我已经将所有样本存储在数组中)。绘制必须高效快速,没有裁剪、闪烁等问题,同时必须平滑。波形图将根据歌曲位置进行“移动”,一些对样本的更改(DSP处理)将实时显示为视觉表示到NSView上。
我熟悉在画布对象上绘制线条、弧线等,并且开发过相关应用程序,但不是在Mac OS X上...
我想问问是否有人可以指导我从哪里开始绘制!Core Animation、OpenGL、简单的覆盖绘制方法等,哪种API最佳?
2个回答

3
我建议您简化操作,创建一个带有audioData属性的NSView子类,并使用Cocoa绘图。您可以调用[view setAudioData:waveArray],这将进而调用[self setNeedsDisplay:YES]
在您的drawRect:方法中,您可以遍历样本并相应地使用NSRectFill()。这里samplevalue值介于0和1之间。
- (void)drawRect:(NSRect)dirtyRect {
    [[NSColor blueColor]set];
    for (id sample in self.waveArray) {
        NSRect drawingRect = NSZeroRect;
        drawingRect.origin.x = [self bounds].origin.x;
        drawingRect.origin.y = [self bounds].origin.y + ([self.waveArray indexOfObject:sample]/([self.waveArray count] - 1.0));
        drawingRect.size.width = [self bounds].size.width/[self.waveArray count];
        drawingRect.size.height = [self bounds].size.height * [sample value];
        NSRectFill(drawingRect);
    }
}

这段代码并不完美,你应该确保只在dirtyRect内绘制样本,以使其更加高效。


你说-(void)drawRect:(NSRect)rect也会被针对控件的某个矩形部分调用?不过,由于[view setAudioData]将强制重绘整个控件(因为有新的波形数据),也许这并不那么重要!或者呢? - Vassilis
-(void)drawRect:(NSRect)rect会被Cocoa随时调用(不应直接调用),并且可能只有部分视图需要重新绘制(例如,如果它在滚动视图中)。出于效率考虑,您应该仅重新绘制需要重新绘制的部分,而不是整个视图。setNeedsDisplay:YES(应在setAudioData:内调用)告诉视图完全重绘。Cocoa View Programming Guide是一些很好的阅读材料。 - spudwaffle
非常感谢,暂时不需要了。如果我需要什么,我一定会联系你的!非常感谢! - Vassilis

0

我会从一个非常长而窄的图像开始,来代表波形的单个条/柱。

我的计划是使用NSTimer,每0.01秒将波浪中的所有条/柱向左移动一格。

循环中的代码大致如下:

for (int x; x < [WaveArray count] ; x++)
{
    UIImageView * Bar = [WaveArray ObjectAtIndex: x];
    [Bar setCenter:CGPointMake(Bar.center.x-1,Bar.center.y)];
}

现在你需要做的就是在正确的高度创建对象并将它们添加到WaveArray中,它们都会向左移动。

感谢您的回答。我的问题是是否要覆盖NSView的绘图方法来执行您提到的所有操作,还是使用OpenGL、Quartz、仅使用AppKit等。我熟悉使用的技术,但对于要使用哪些API完全不了解。 - Vassilis
我其实本来想从一个视图控制器中完成这个的哈哈。 - Necro
我甚至不会有自定义视图。 - Necro
Xmm,我需要更高效的东西...我想 :) - Vassilis
(1) UIImageView在Mac OS X上不存在, (2) 为什么要在视图控制器中进行所有绘图,而不是在视图中? - Peter Hosey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接