使用 UIPanGestureRecognizer 拖动 + 旋转触摸下车

Posted

技术标签:

【中文标题】使用 UIPanGestureRecognizer 拖动 + 旋转触摸下车【英文标题】:Drag + Rotation using UIPanGestureRecognizer touch getting off track 【发布时间】:2012-04-28 04:53:28 【问题描述】:

我正在使用 UIPanGestureRecognizer 进行一些拖动和旋转计算。旋转角度正确,拖动位置几乎正确。问题是当你绕过盒子的中心时,需要根据角度进行调整,我不知道怎么做。

我已经包含了 180 度旋转的图片,但旋转过程中手指在哪里。我只是不知道如何调整以使块适当地停留在您的手指上。这是一个视频,只是为了澄清,因为这是奇怪的行为。 http://tinypic.com/r/mhx6a1/5

编辑:这是一个真实世界的视频,讲述了应该发生的事情。问题在于,在 iPad 视频中,您的手指正在移动,而在现实世界中,您的手指将被固定在移动项目的特定位置。所需的数学运算是沿着与实际中心不同的角度调整您的触摸位置。我只是无法弄清楚数学。 http://tinypic.com/r/4vptnk/5

非常感谢!

- (void)handlePan:(UIPanGestureRecognizer *)gesture

    if (gesture.state == UIGestureRecognizerStateBegan) 
        // set original center so we know where to put it back if we have to.
        originalCenter = dragView.center;

     else if (gesture.state == UIGestureRecognizerStateChanged) 
        [dragView setCenter:CGPointMake( originalCenter.x + [gesture translationInView:self.view].x , originalCenter.y + [gesture translationInView:self.view].y )];

        CGPoint p1 = button.center;
        CGPoint p2 = dragView.center;

        float adjacent = p2.x-p1.x;
        float opposite = p2.y-p1.y;

        float angle = atan2f(adjacent, opposite); 

        [dragView setTransform:CGAffineTransformMakeRotation(angle*-1)];

    

【问题讨论】:

该视频非常有用,感谢您这样做。块是否应该围绕信息按钮“旋转”,就好像信息按钮是地上的一根棍子,这样您就在寻找棍子上的碰撞检测?如果是这种情况,那么您正在寻找的数学更多是关于矩形边缘和信息按钮外边缘之间的距离。当你用手指推动它时,我可能有一些代码可以帮助解决该块的任意位置。 这只是一个功能的小测试项目,它将成为一个更大的项目。信息按钮代表一个小的圆形 UIButton。该块代表 UIImageView 矩形。它应该旋转并始终面向按钮。问题是,当用户拖动块时,手指会错位,这会导致不自然的感觉运动。我需要一种方法来将手指保持在积木上的同一位置。我认为这与根据与原始中心的角度和触摸距离调整中心有关。我只是无法弄清楚数学。 所以问题是这样的:UIImageView 是否应该与圆形 UIButton 保持“联系”?我的代码将可以被认为是工具提示的内容与正在旋转的形状的一侧保持正好 20 像素,因此对于正在旋转的矩形,工具提示必须从矩形的中心“滑出”作为一个角走过来,然后随着矩形的窄边移动,滑回更靠近中心的位置。 另一个问题:是否有理由使用 UIPanGestureRecognizer 而不仅仅是 touchesMoved:?我选择了一个不同项目的平底锅,因为我想要速度,但我认为这在你的项目中并不重要。 矩形不应绑定到按钮,除非通过旋转。它应该能够拖动屏幕上的任何位置。我只是在视频中保持关闭以强调手指是如何偏离轨道的。我选择了 UIPanGestureRecognizer,因为那是我被要求使用的。然而,这只是一个数学问题,touchesMoved 不会改变结果。 【参考方案1】:

我终于解决了这个问题并让它完美运行。坚持是对的吗??

这是解决方案的代码,其中包含几个 cmets 来解释更改。

- (void)handlePan:(UIPanGestureRecognizer *)gesture

    if (gesture.state == UIGestureRecognizerStateBegan) 
        // Get the location of the touch in the view we're dragging.
        CGPoint location = [gesture locationInView:dragView];

        // Now to fix the rotation we set a new anchor point to where our finger touched. Remember AnchorPoints are 0.0 - 1.0 so we need to convert from points to that by dividing
        [dragView.layer setAnchorPoint:CGPointMake(location.x/dragView.frame.size.width, location.y/dragView.frame.size.height)];


     else if (gesture.state == UIGestureRecognizerStateChanged) 
        // Calculate Our New Angle
        CGPoint p1 = button.center;
        CGPoint p2 = dragView.center;

        float adjacent = p2.x-p1.x;
        float opposite = p2.y-p1.y;

        float angle = atan2f(adjacent, opposite); 

        // Get the location of our touch, this time in the context of the superview.
        CGPoint location = [gesture locationInView:self.view];

        // Set the center to that exact point, We don't need complicated original point translations anymore because we have changed the anchor point.
        [dragView setCenter:CGPointMake(location.x, location.y)];

        // Rotate our view by the calculated angle around our new anchor point.
        [dragView setTransform:CGAffineTransformMakeRotation(angle*-1)];

    

希望我一个月以上的奋斗和解决方案可以在未来帮助其他人。快乐编码:)

【讨论】:

感谢您在弄清楚后发布您自己问题的答案。非常感谢。这对我很有帮助。【参考方案2】:

基于触摸事件 https://github.com/kirbyt/KTOneFingerRotationGestureRecognizer

帮我解决了类似的问题

【讨论】:

以上是关于使用 UIPanGestureRecognizer 拖动 + 旋转触摸下车的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 UIPanGestureRecognizer 移动对象时会有延迟?

UIPanGestureRecognizer ***视图未获取事件,子视图使用它们

在 UITableView 上滑动删除以使用 UIPanGestureRecognizer

在 UIPanGestureRecognizer 中使用velocityInView

使用 UIPanGestureRecognizer 拖动 + 旋转触摸下车

使用 UIPanGestureRecognizer 移动和缩放 UIView