Поворот NSImage с помощью NSAffineTransform или без него
-
18-09-2019 - |
Вопрос
У меня есть NSImage, нарисованный в подклассе NSView.В предыдущем вопросе мне помогли нарисовать его вертикально в левом верхнем углу.Теперь я хочу иметь возможность вращать изображение.У меня есть кнопка, которая увеличивает переменную поворота %4, а затем я умножаю ее на -90, чтобы найти угол поворота.Затем я использую NSAffineTransform, чтобы повернуть изображение и перевести его обратно на экран.Однако, похоже, это работает не так, как я ожидаю.У меня есть две проблемы.
1) При повороте часть изображения, находящаяся в области, которой не было в предыдущем кадре, рисуется правильно.Однако зелье, которое было там раньше, остается исходным изображением.Это означает, что после нескольких поворотов появляется квадрат исходного вертикального изображения, а затем прямоугольник ниже или слева от повернутого изображения.
2) Когда я изменяю размер окна, изображение перерисовывается (как должно) в исходной вертикальной ориентации (а не должно).
По сути, я прихожу к выводу, что NSAffineTransform работает не так, как я думаю.Есть ли другой способ повернуть (и перевести) изображение?Спасибо
большой кусок кода:(код между «WORKS» и «endworks» — это рабочий код, позволяющий просто нарисовать изображение.Это из моего предыдущего вопроса).
[СТАРЫЙ КОД УДАЛЕН, заменен на новый код ниже]
Спасибо
РЕДАКТИРОВАТЬ:Еще немного исследований показало, что вместо NSAffineTtransform я могу вращать представление.Кажется, это работает лучше.Однако я не могу заставить перевод работать правильно.новый код ниже (исходный код удален для экономии места)
- (void)drawRect:(NSRect)rect
{
//WORKS
NSRect frame;
frame.origin = NSZeroPoint;
frame.size = [image size];
// end works
float deltaX, deltaY, height, width;
// if the rotate button was just clicked, we need to rotate by 90 deg, otherwise not
double rotateDeg = justRot ? -90.0 : 0;
justRot = NO;
// rotate
deltaX = 0;
deltaY = 0;
// translate to account for rotation
height = [image size].height;
width = [image size].width;
switch (rotation)
{
case 0:
NSLog(@"No rotation ");
break;
case 1:
deltaX += width;
break;
case 2:
deltaX += width;
deltaY += height;
break;
case 3:
deltaY += height;
break;
}
NSPoint orig;
if (rotation != 0)
{
orig.x = -100;
orig.y = -100;
}
[self rotateByAngle: rotateDeg];
NSLog(@"orig %f %f", orig.x, orig.y);
// WORKS
[self setFrame: frame];
[image drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
// end works
[self translateOriginToPoint: orig];
}
Решение
Хорошо, для истории, если у кого-то еще возникнет этот вопрос, вот ответ, который я придумал:
Вращение кадра остается в drawRect, все остальное перемещается в метод Rotate:
-(void)rotate
{
float deltaX, deltaY, height, width;
rotation = (rotation +1) % 4 ;
deltaX = 0;
deltaY = 0;
// translate to account for rotation
height = [image size].height;
width = [image size].width;
switch (rotation)
{
case 0:
NSLog(@"No rotation ");
deltaY -= width;
break;
case 1:
deltaY -= height;
break;
case 2:
deltaX += height-width;
deltaY -= height ;
break;
case 3:
deltaX += height-width;
deltaY -= width;
break;
}
NSPoint orig;
orig.x = deltaX;
orig.y = deltaY;
[self rotateByAngle: 90.0];
[self translateOriginToPoint: orig];
[self setNeedsDisplay:YES];
}
Другие советы
Я предполагаю, что вы хотели бы повернуть изображение вокруг его центра.В этом случае вам нужно переместить начало аффинного преобразования в центр изображения, затем повернуть, а затем перевести обратно.Теперь, если у вас остались артефакты предыдущей позиции, возможно, это потому, что вы не вызвали -[NSView setNeedsDisplayInRect:] с правильными прямоугольниками.Помните, что вам необходимо аннулировать как предыдущую, так и новую позицию изображения.
Обновлять:Я только что заметил, что вы меняете рамку представления изнутри drawRect:.Уже слишком поздно менять рамку.Вместо этого нарисуйте изображение в правильном месте, не меняя рамку вида.
Взгляните на мой старый пример кода Transformed Image: http://developer.apple.com/mac/library/samplecode/Transformed_Image/index.html