La rotation d'une NSImage avec ou sans NSAffineTransform
-
18-09-2019 - |
Question
J'ai un NSImage en cours d'élaboration sur une sous-classe de NSView. Dans une question précédente, j'ai été aidé à dessiner debout dans le coin supérieur gauche. Maintenant, je veux être en mesure de faire pivoter l'image. J'ai un bouton qui incrémente une variable de rotation 4%, puis-je multiplier par -90 pour trouver l'angle de rotation. J'utilise ensuite un NSAffineTransform pour faire pivoter l'image, et retraduire sur l'écran. Cependant, il ne semble pas fonctionner comme je l'attends à. J'ai deux problèmes.
1) Lorsque je tourne, la partie de l'image qui se trouve dans une zone qui n'a pas été dans la trame précédente est dessiné correctement. Cependant, la potion qui était auparavant il reste que l'image originale. Cela signifie que, après plusieurs rotations, il y a un carré de l'image verticale d'origine puis un rectangle ci-dessous ou à gauche de l'image rotate.
2) Lorsque je re-dimensionner la fenêtre, l'image redraws (comme il se doit) dans l'orientation verticale d'origine (comme il se doit pas).
En fait, je viens à la conclusion que NSAffineTransform ne fonctionne pas la façon dont je pense qu'il fait. Y at-il une autre façon de faire tourner (et traduire) l'image? merci
gros morceau de code:. (. Code entre « œuvres » et « travaux de fin » est le code de travail pour dessiner seulement l'image Il est venu de ma question précédente)
[CODE ANCIEN SUPPRIME, remplacé par le code inférieur nouveau]
Merci
EDIT: Un peu plus de recherche trouve qu'au lieu de faire un NSAffineTtransform je peux faire pivoter la vue. Cela semble fonctionner mieux. Cependant, je ne peux pas obtenir la traduction de travailler tout à fait raison. nouveau code ci-dessous (code d'origine supprimé pour économiser l'espace)
- (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];
}
La solution
Ok, pour l'histoire, au cas où quelqu'un d'autre a cette question est ici la réponse que je suis venu avec:
La rotation du cadre reste dans le drawRect, tout le reste passe à la méthode 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];
}
Autres conseils
Je devine que vous souhaitez faire pivoter l'image à propos de son centre. Si oui, vous avez besoin de traduire l'origine de la transformation affine au centre de l'image, puis faites pivoter, puis retraduire. Maintenant, si vous avez des artefacts de la position previos reste, il est probablement parce que vous n'avez pas appelé - [NSView setNeedsDisplayInRect:] avec les rectangles corrects. Rappelez-vous que vous avez besoin d'invalider les deux images précédentes et de nouvelles positions.
Mise à jour: Je viens de remarquer que vous changez le cadre de la vue de l'intérieur drawRect :. C'est trop tard pour changer le cadre. Au lieu de cela, dessiner l'image dans l'emplacement correct sans changer le cadre de la vue.
Jetez un oeil à mon ancien exemple de code d'image Transformé à: http : //developer.apple.com/mac/library/samplecode/Transformed_Image/index.html