【问题标题】:Can i move the origin when doing a rotation transform in Quartz 2D for the iPhone?在 iPhone 的 Quartz 2D 中进行旋转变换时,我可以移动原点吗?
【发布时间】:2009-03-22 04:48:14
【问题描述】:

很抱歉,如果这很明显或在其他地方被覆盖,但我整天都在谷歌上搜索,还没有找到真正有效的解决方案。

我的问题如下:我目前正在全屏 UIView 中绘制图像,例如,我们会说图像在 UIView 的右下角。我想在该图像的中心进行旋转变换(CGAffineTransformMakeRotation),但是,默认情况下,旋转命令围绕它自身的 UIView 的中心旋转。结果,当我旋转时,我的图像会在屏幕上移动,而不是停留在原地并围绕自己的中心旋转。

根据我收集到的信息,我需要翻译我的上下文,以便原点(UIView 的中心)位于我的图像中心,旋转,然后通过翻译回原始位置来恢复上下文。

以下是我最接近的工作,但问题是图像旋转时,它在旋转时向下移动。我认为这是由动画补间第一步平移和第三步平移引起的,而不是仅仅意识到平移的起点和终点是相同的......

// Before this i'd make a call to a function that draws a path to a passed in context
CGAffineTransform inverseTranslation = CGAffineTransformMakeTranslation( transX, transY );
CGAffineTransform translation = CGAffineTransformMakeTranslation( -transX, -transY );
CGAffineTransform rot = CGAffineTransformMakeRotation( 3.14 );
CGAffineTransform final = CGAffineTransformConcat( CGAffineTransformConcat( inverseTranslation, rot ), translation );
// Then i apply the transformation animation like normal using self.transform = final etc etc

我也尝试过 CGContextTranslateCTM 和 CGContextSaveGState/UIGraphicsPushContext 之类的东西,但这些似乎效果不大。

我已经为此奋斗了好几天,我目前的解决方案似乎很接近,但我不知道如何摆脱这种翻译补间。有没有人对此有解决方案或更好的方法?

[更新] 目前我正在绘制以 UIview 的中心为中心的图像,然后将 UIView.center 属性设置为我想要旋转的原点,然后执行旋转命令。看起来有点像 hack,但在我得到真正的翻译工作之前,这是我唯一的选择。 谢谢!

【问题讨论】:

    标签: iphone core-animation 2d quartz-graphics


    【解决方案1】:

    duncanwilcox 的答案是正确的,但他忽略了将视图层的锚点更改为要旋转的点的部分。

    CGSize sz = theview.bounds.size;
    // Anchorpoint coords are between 0.0 and 1.0
    theview.layer.anchorPoint = CGPointMake(rotPoint.x/sz.width, rotPoint.y/sz.height);
    [UIView beginAnimations:@"rotate" context:nil];
    theview.transform = CGAffineTransformMakeRotation( 45. / 180. * M_PI );
    [UIView commitAnimations];
    

    这在此处记录:http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html

    【讨论】:

    • 快速评论 - 编辑显示您在使用 pi 值时应该使用 math.h 常量。 M_PI_4、M_PI_2、M_PI 比所有的舍入误差更好更准确:)
    【解决方案2】:

    这也是一种选择:简单地改变基础;-)

    CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
    transform = CGAffineTransformRotate(transform, angle);
    transform = CGAffineTransformTranslate(transform,-x,-y);
    

    (x,y) 是你喜欢的旋转中心

    【讨论】:

      【解决方案3】:

      旋转发生在视图层的锚点周围。 anchorPoint 的默认值是中心 (0.5, 0.5),因此没有平移的单独旋转就足够了。

      做了一个快速测试,这对我有用:

      [UIView beginAnimations:@"rotate" context:nil];
      self.transform = CGAffineTransformMakeRotation( 45. / 180. * 3.14 );
      [UIView commitAnimations];
      

      【讨论】:

      • 也许我的描述有点误导。我正在上下文中绘制一些东西(我称它为图像,但它只是我使用上下文命令绘制的东西)并且它不在上下文的中心。我想像上下文的中心在我的“图像”的中心一样旋转。
      • 快速评论 - 编辑显示您在使用 pi 值时应该使用 math.h 常量。 M_PI_4、M_PI_2、M_PI 比所有的舍入误差更好更准确:)
      【解决方案4】:

      如果您不希望出现动画,而只是设置新的旋转,您可以使用这个:

      CGFloat newRotation = 3.14f 
      
      [UIView beginAnimations:nil context:NULL];
      [UIView setAnimationDuration:0.0]; // no tweening
      CGAffineTransform transform = CGAffineTransformMakeRotation(newRotation);
      self.transform = transform;
      [UIView commitAnimations];
      

      旋转确实应该围绕 UIView 的中心进行。 将 animationDuration 设置为零保证不会发生补间。

      请确保您不要每秒执行 60 次此操作。使用这些工具创建类似动画的游戏非常诱人。这类动画并不完全适用于基于帧到帧的“大量精灵到处飞”的游戏。

      为此 - 我一直在走这条路 - 唯一的出路是 OpenGL。

      【讨论】:

      • 好吧,我确实想要旋转动画,也许我可以使用你的 0 秒持续时间进行前后翻译,因为 CGContextTranslateCTM 似乎不起作用......
      • 确保在执行 CGContextTranslateCTM 之前保存 CGContext 状态。然后恢复状态。如果您只是在上下文中绘制后翻译 CTM,它没有(明显的)效果。
      猜你喜欢
      • 2011-09-09
      • 2016-12-12
      • 2015-01-01
      • 1970-01-01
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      相关资源
      最近更新 更多