【问题标题】:Rotating an NSImage with or without NSAffineTransform使用或不使用 NSAffineTransform 旋转 NSImage
【发布时间】:2009-08-18 14:12:09
【问题描述】:

我在 NSView 的子类上绘制了一个 NSImage。在上一个问题中,有人帮我把它画在左上角。现在,我希望能够旋转图像。我有一个增加旋转变​​量 %4 的按钮,然后我将其乘以 -90 以找到旋转角度。然后我使用 NSAffineTransform 旋转图像,并将其转换回屏幕上。但是,它似乎并没有按照我期望的方式工作。我有两个问题。

1) 当我旋转时,位于前一帧之外的区域中的图像部分会被正确绘制。然而,先前存在的药水仍然是原始图像。这意味着经过几次旋转后,原始直立图像会出现一个正方形,然后在旋转图像的下方或左侧会出现一个矩形。

2) 当我重新调整窗口大小时,图像会以原始垂直方向重绘(应该如此)(因为它不应该如此)。

基本上,我得出的结论是 NSAffineTransform 不能像我认为的那样工作。还有其他方法可以旋转(和平移)图像吗?谢谢

大代码块:(“WORKS”和“end works”之间的代码是用于绘制图像的工作代码。它来自我之前的问题)。

[旧代码已删除,下方已替换为新代码]

谢谢

编辑:更多研究发现,我可以旋转视图,而不是执行 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];    
}

【问题讨论】:

    标签: objective-c cocoa nsimage image-rotation nsaffinetransform


    【解决方案1】:

    好的,对于历史,如果其他人有这个问题,这是我想出的答案:

    框架旋转停留在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];
    }
    

    【讨论】:

      【解决方案2】:

      我猜你想围绕它的中心旋转图像。如果是这样,您需要将仿射变换的原点平移到图像的中心,然后旋转,然后再平移回来。现在,如果您留下了 previos 位置的工件,这可能是因为您没有使用正确的矩形调用 -[NSView setNeedsDisplayInRect:]。请记住,您需要使之前和新位置的图像都无效。

      更新:我刚刚注意到您正在从 drawRect: 中更改视图的框架。改变框架为时已晚。相反,在正确的位置绘制图像而不更改视图的框架。

      【讨论】:

      • 好吧,与其翻译图像,然后再将其翻译回来,只翻译旋转后的图像更容易......我正在做一个没有矩形的直接“setNeedsDisplay”,所以它应该使整件事,不是吗?更改视图框架只是为了使其形状正确。这样,当我更改窗口大小时,它就知道在哪里创建滚动条...
      • 我认为我说得不够有力。我认为不支持在绘制矩形期间更改视图的框架。我能找到的最好的支持证据在这里:developer.apple.com/releasenotes/Cocoa/AppKit.html。请参阅有关视图将绘制方法的注释。他们特意说支持在 viewWillDraw 期间更改框架,这对我来说意味着不支持在 drawRect: 期间更改它。
      • hrm,好吧,它似乎可以改变框架的形状,以便滚动条正确出现......但我可以将它放入旋转方法中...... .它似乎没有任何帮助......
      • 绝对不支持在 -drawRect: 期间更改框架。 -drawRect:可以随时发送,不希望有任何副作用。
      【解决方案3】:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-30
        • 1970-01-01
        • 1970-01-01
        • 2016-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多