#objective-c #cocoa #opengl #animation #nsview
#objective-c #какао #opengl #Анимация #nsview
Вопрос:
Мне нужно нарисовать форму волны в NSView. (У меня есть все выборки в массиве). Рисование должно быть эффективным и действительно быстрым, Без обрезки, мерцания и т. Д., Оно должно быть плавным. Форма сигнала будет «перемещаться» в соответствии с положением песни, и некоторые изменения в сэмплах (обработка DSP) будут показаны в виде визуального представления в NSView в режиме реального времени.
Я знаком с рисованием линий, дуг и т. Д. На объектах canvas, и я разработал приложения, делающие такие вещи, но не на Mac OS X…
Я хочу спросить, может ли кто-нибудь подсказать мне, с чего начать рисовать! Основная анимация, OpenGL, простые переопределяющие методы рисования, ?? и т.д. Какой API-интерфейс лучше всего использовать?
Ответ №1:
Я бы сделал это просто и создал NSView
подкласс со audioData
свойством, которое использует рисование Cocoa. Вы могли бы вызвать [view setAudioData:waveArray]
который, в свою очередь, вызовет [self setNeedsDisplay:YES]
.
Затем в вашем drawRect:
методе вы можете перебирать выборки и использовать NSRectFill()
их соответствующим образом. Здесь sample
value
значение находится между 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
.
Комментарии:
1. Вы говорите, что -(void)drawRect:(NSRect)rect вызывается частично и для определенного rect элемента управления? В любом случае … поскольку [просмотр setAudioData] заставит перерисовать весь элемент управления (из-за новых волновых данных), может быть, это не так уж и важно !? или это так?
2.
-(void)drawRect:(NSRect)rect
вызывается по желанию Cocoa (и никогда не должен вызываться напрямую), и возможно, что потребуется перерисовать только часть представления (например, если оно находится в режиме прокрутки). В целях эффективности вам следует перерисовывать только то, что необходимо перерисовать, а не весь вид.setNeedsDisplay:YES
(который должен вызываться внутриsetAudioData:
) сообщает виду полностью перерисовать. Руководство по программированию Cocoa View было бы хорошим чтением.3. о, большое вам спасибо, пока в этом нет необходимости. Если мне понадобится что-то, я обязательно свяжусь! Большое спасибо!
Ответ №2:
Я бы начал с действительно длинного и тонкого изображения, чтобы представить одну строку / столбец для формы сигнала.
Мой план состоял бы в том, чтобы иметь 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, и все они будут перемещены влево.
Комментарии:
1. Спасибо за ваш ответ. Моя проблема заключается в том, следует ли переопределять методы рисования NSView для выполнения всех упомянутых вами действий или использовать OpenGL, Quartz, просто AppKit и т. Д. Я знаком с технологией использования, но совсем не с тем, какие API использовать.
2. Я на самом деле улучшил все это с помощью контроллера представления, ха-ха.
3. У меня даже не было бы пользовательского представления
4. Хмм, мне нужно что-то более эффективное… Я думаю 🙂
5. (1) UIImageView не существует в Mac OS X, и (2) почему вы должны выполнять все отрисовки в контроллере представления вместо представления?