基于UITouch旋转UIView
我正在开发一个绘图应用程序。
我希望用户能够将形状“拖放到”屏幕上,然后根据需要移动、调整大小或旋转它。
问题出在旋转上。我的移动和调整大小工作正常。
我之前使用了一个相当复杂且内存/处理器密集型的过程来完成此操作,现在我正在尝试改进该过程。
我搜索了又搜索,但没有找到与我想要做的类似的答案。
基本上,假设用户在“表面”上放置了一个正方形。然后,他们点击它并获得一些手柄。他们可以触摸任意位置并平移以移动正方形(已工作),触摸并拖动调整大小手柄以调整正方形大小(已工作),或者抓住旋转手柄以使正方形绕其中心旋转。
我研究过使用 UIBezierPath 绘制正方形,或者只是让它成为我填充的 UIView 的子类。
无论哪种情况,我都尝试旋转 UIView 本身,而不是内部的某些内容。每次我尝试旋转视图时,要么什么也没有发生,视图腾出屏幕,要么只旋转一点然后停止。
这是我尝试过的一些代码(这不起作用,我尝试了很多不同的方法):
- (void) rotateByAngle:(CGFloat)angle
{
CGPoint cntr = [self center];
CGAffineTransform move = CGAffineTransformMakeTranslation(-1 * cntr.x, -1 * cntr.y);
[[self path] applyTransform:move];
CGAffineTransform rotate = CGAffineTransformMakeRotation(angle * M_PI / 180.0);
[[self path] applyTransform:rotate];
[self setNeedsDisplay];
CGAffineTransform moveback = CGAffineTransformMakeTranslation(cntr.x, cntr.y);
[[self path] applyTransform:moveback];
}
如果它不明显,这里的想法是将视图移动到原点( 0,0),围绕该点旋转,然后将其移回。
如果您想知道,“角度”计算正确。我还将上面的代码包装在 [UIView beginAnimations:nil context:NULL]
/[UIView commitAnimations]
块中。
是否可以将 UIView 旋转“自定义”量?我之前见过/做过它,我用动画控制旋转,但在这些示例中,控件总是以“方形”结束(即,它旋转 1 个或多个整圈并返回到其起始方向)。
是否可以“实时”执行此旋转以响应 UITouches?我是否需要将正方形绘制为 UIView 图层中的项目并旋转图层?
如您所知,我之前所做的工作是由一组线条或 UIBezierPaths 绘制的形状。我会将 CGAffineTransform 应用于数据,然后调用 drawRect: 方法,该方法将在自定义 UIView 内重新绘制对象。这个 UIView 将承载相当多的此类项目,所有这些项目都需要在其中一个需要时重新绘制。
因此,我试图通过创建一堆 UIView 子类来提高应用程序的性能,这些子类只会在用户使用它们执行某些操作时获得重新绘制的命令。苹果 iPad 的 Keynote 似乎使用 UIGestureRecognizers 来实现这一点,因为你必须使用两根手指来旋转添加的形状。这是要走的路吗?
想法?
谢谢!
I'm working on a drawing app.
I want the user to be able to "drop" a shape on the screen and then move, resize or rotate it as desired.
The problem is with the rotation. I have the moving and resizing working fine.
I did this before with a rather complex and memory/processor-intensive process, which I am now trying to improve.
I've searched and searched but haven't found an answer similar to what I'm trying to do.
Basically, let's say the user drops a square on the "surface". Then, they tap it and get some handles. They can touch anywhere and pan to move the square around (working already), touch and drag on a resize handle to resize the square (working already), or grab the rotation handle to have the square rotate around its center.
I've looked into drawing the square using UIBezierPath or just having it be a subclass of UIView that I fill.
In either case, I'm trying to rotate the UIView itself, not some contents inside. Every time I try to rotate the view, either nothing happens, the view vacates the screen or it rotates just a little bit and stops.
Here's some of the code I've tried (this doesn't work, and I've tried a lot of different approaches to this):
- (void) rotateByAngle:(CGFloat)angle
{
CGPoint cntr = [self center];
CGAffineTransform move = CGAffineTransformMakeTranslation(-1 * cntr.x, -1 * cntr.y);
[[self path] applyTransform:move];
CGAffineTransform rotate = CGAffineTransformMakeRotation(angle * M_PI / 180.0);
[[self path] applyTransform:rotate];
[self setNeedsDisplay];
CGAffineTransform moveback = CGAffineTransformMakeTranslation(cntr.x, cntr.y);
[[self path] applyTransform:moveback];
}
In case it isn't obvious, the thinking here it to move the view to the origin (0,0), rotate around that point and then move it back.
In case you're wondering, "angle" is calculated correctly. I've also wrapped the code above in a [UIView beginAnimations:nil context:NULL]
/[UIView commitAnimations]
block.
Is it possible to rotate a UIView a "custom" amount? I've seen/done it before where I animate a control to spin, but in those examples, the control always ended up "square" (i.e., it rotated 1 or more full circles and came back to its starting orientation).
Is it possible to perform this rotation "real-time" in response to UITouches? Do I need to draw the square as an item in the layer of the UIView and rotate the layer instead?
Just so you know, what I had working before was a shape drawn by a set of lines or UIBezierPaths
. I would apply a CGAffineTransform
to the data and then call the drawRect: method, which would re-draw the object inside of a custom UIView. This UIView would host quite a number of these items, all of which would need to be re-drawn anytime one of them needed it.
So, I'm trying to make the app more performant by creating a bunch of UIView subclasses, which will only get a command to re-draw when the user does something with them. Apple's Keynote for the iPad seems to accomplish this using UIGestureRecognizers, since you have to use two fingers to rotate an added shape. Is this the way to go?
Thoughts?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能会有所帮助。
This might help.
对于简单的旋转,您可能会忽略动画:
我使用一个简单的 NSTimer 来控制动画。
for just simple rotation you might leave out the Animation:
I use a simple NSTimer to control a animation.