在 iPhone 的 Quartz 2D 中进行旋转变换时可以移动原点吗?

发布于 2024-07-15 18:17:10 字数 1286 浏览 10 评论 0原文

抱歉,如果这很明显或在其他地方有所涉及,但我已经在谷歌上搜索了一整天,但没有找到实际有效的解决方案。

我的问题如下:我当前正在全屏 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 属性设置为我想要旋转的原点,然后执行旋转命令。 看起来有点像黑客,但在我能让真正的翻译工作之前,这是我唯一的选择。 谢谢!

Sorry if this is obvious or covered elsewhere, but i've been googling all day and haven't found a solution that actually worked.

My problem is as follows: I am currently drawing an image in a full screen UIView, for examples sake we'll say the image is in the bottom right corner of the UIView. I'd like to do a rotation transform(CGAffineTransformMakeRotation) at the center of that image, however, by default the rotation command rotates around the center of the UIView it self. As a result, my image moves around the screen when i rotate instead of it staying in place and rotating around its own center.

From what i've gathered, i need to translate my context so that the origin(center of the UIView) is at the center of my image, Rotate, and then restore the context by translating back to the original spot.

The following is the closest thing i've gotten to work, but the problem is that while the image is rotating, it moves downward while it's rotating. I think this is caused by animation tweening the 1st step translate and 3rd step translate instead of just realizing that the beginning and end point on the translates would be the same...

// 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

I've also tried stuff like CGContextTranslateCTM and CGContextSaveGState/UIGraphicsPushContext, but these seem to have little effect.

I've been fighting with this for days and my current solution seems close, but i have no clue how to get rid of that translating tweening. Does anyone have a solution for this or a better way to go about this?

[update]
For the time being i'm drawing my image centered at the UIview's center and then setting the UIView.center property to the origin i'd like to rotate and then doing the rotate command. Seems like a bit of a hack, but until i can get the real translates working it's my only choice.
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鸩远一方 2024-07-22 18:17:10

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

duncanwilcox' answer is the right one, but he left out the part where you change the anchor of the view's layer to the point you want to rotate around.

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];

This is documented here: http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html

陌生 2024-07-22 18:17:10

这也是一个选项:简单地更改基础;-)

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

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

This is also an option: a simple change of basis ;-)

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

where (x,y) is the rotation center you like

一向肩并 2024-07-22 18:17:10

旋转围绕视图图层的锚点发生。 锚点的默认值是中心 (0.5, 0.5),因此仅旋转而不进行平移就足够了。

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

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

Rotation happens around the anchorPoint of the view's layer. The default for the anchorPoint is the center (0.5, 0.5), so the rotation alone without the translations should suffice.

Did a quick test and this works for me:

[UIView beginAnimations:@"rotate" context:nil];
self.transform = CGAffineTransformMakeRotation( 45. / 180. * 3.14 );
[UIView commitAnimations];
难理解 2024-07-22 18:17:10

如果您不想发生动画,而只是设置新的旋转,则可以使用以下方法:

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。

If you don't want an animation to occur, but just set the new rotation, you can use this:

CGFloat newRotation = 3.14f 

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

The rotation should indeed take place around the center of the UIView. Setting the animationDuration to zero garantees no tweening should happen.

Be sure though you don't do this 60 times a second. It's very tempting to create game like animations with these tools. These kind of animations aren't exactly meant for a frame to frame based, "lots of sprites flying everywhere" game.

For that - and I've been down that road - the only way to go, is OpenGL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文