【问题标题】:Using UIPanGestureRecognizer to rotate a UIView around a certain point使用 UIPanGestureRecognizer 围绕某个点旋转 UIView
【发布时间】:2012-11-30 11:58:28
【问题描述】:

我正在尝试创建允许用户从窗口一侧拉出面板的动画。少量视图将在右上角可见,通过拉动它,视图将向外旋转,固定在屏幕的右下角。希望这些图像显示了我想要实现的目标(右侧的纸张表明视图的一部分将被隐藏。我希望用户能够拖动它,而不是滑动或点击。

谁能指出我如何实现这一目标的正确方向?我对 iOS 中的动画很陌生。我已经让平移手势工作了,但我需要这个点来旋转。我可以设置视图的 .center 属性,但这样做只是将整个视图移动到该点,所以我需要一个 center 来旋转,我认为这实际上不是视图的中间?

编辑:我编写了一个有效的方法,但视图并没有“卡”在用户的手指上。我可以拖动手指,比如 45 度,但视图会移动得更多。不知道如何同步它们,有什么想法吗?

- (void) swipeSidebarOpen: (UIPanGestureRecognizer *) recognizer {
    //[self openOrCloseSideBar: YES];
    _sidebarView.layer.anchorPoint = CGPointMake(1.0, 1.0);
    _sidebarView.layer.position = CGPointMake(510, 330);

    UIView *shuttle = [recognizer view];

    if ([recognizer state] == UIGestureRecognizerStateBegan || [recognizer state] == UIGestureRecognizerStateChanged) {
        CGPoint vel = [recognizer velocityInView:[recognizer view]];

        if (vel.x > 0) {
            [recognizer view].transform = CGAffineTransformRotate([[recognizer view] transform], M_PI / 80.0f);
            [recognizer setTranslation: CGPointZero inView:[shuttle superview]];
        } else {
            [recognizer view].transform = CGAffineTransformRotate([[recognizer view] transform], -M_PI / 80.0f);
            [recognizer setTranslation: CGPointZero inView:[shuttle superview]];
        }
    }
}

【问题讨论】:

    标签: objective-c ios core-animation uigesturerecognizer uipangesturerecognizer


    【解决方案1】:

    有点晚了,但我写了一些代码来处理单指使用的平移、缩放和缩放。标准手势在微调工作或在出租车后部弹跳时缺乏一定的准确性。

    这两件事可能会对你有所帮助。旋转手势目标方法能够从捏合识别器或平移接受。不过,您需要跟踪平移识别器的第一个触摸点落在哪里,因为您将计算其当前点与手势起点之间的角度。您还需要保存屏幕中心。对我来说,我将所有这些点都放入了窗口的坐标系中,因此您必须选择要使用的点并坚持使用。

    CGFloat /* midpoint, startpoint, point */
    CGPointAngleATan2(CGPoint mp, CGPoint sp, CGPoint p)
    {
        CGFloat angle = 0;
        CGFloat sAngle = atan2(sp.y-mp.y,sp.x-mp.x);
        CGFloat pAngle = atan2(p.y-mp.y,p.x-mp.x);
        angle = pAngle-sAngle;
        return angle;
    }
    
    
    - (CGFloat)calculateRotation:(UIGestureRecognizer *)sender;
    {
        CGFloat rotation;
    
        if ([sender respondsToSelector:@selector(rotation)]){
            rotation = [(UIRotationGestureRecognizer *)sender rotation];
        } else {
            // convert to window co-ordinates, app specific so change if needed
            CGPoint point = [sender locationInView:self.view.window];
            rotation = CGPointAngleATan2(screenCenter,firstTouch,point);
        }
        return rotation;
    }
    

    【讨论】:

      【解决方案2】:

      默认情况下,视图将围绕其中心旋转,但您可以通过为视图 layer 设置另一个 anchorPoint 来更改它。 (您需要导入核心动画来做到这一点(QuartzCore.framework))。

      锚点已标准化(X 和 Y 都从 0 变为 1)。默认情况下它在中心 (0.5, 0.5) 但您想将其更改为右下角 (1.0, 1.0)。

      myView.layer.anchorPoint = CGPointMake(1.0, 1.0);
      

      更改anchorPoint 将在屏幕上直观地移动您的视图,以便超级视图中视图层的position 与视图旋转的点相同。

      myView.layer.position = theFixedHerePoint; // The point you are showing in your drawing...
      

      例如:如果超级视图从 (0,0) 变为 (100, 100),则 myView 的 position 应该是 右下角应该在的点,而不是在哪里myView 的中心是。如下图所示(X 是锚点 (1, 1) 和位置 (95, 95))。 请注意,95 只是一个任意值。

      ┌───────────────────┐
      │ superview         │
      │                   │
      │      ┌──────────┐ │
      │      │ myView   │ │
      │      │          │ │
      │      │          │ │
      │      └──────────X │
      └───────────────────┘
      

      现在,当您平移时,您只需设置适当的旋转变换,视图将围绕其右下角旋转。

      【讨论】:

      • 谢谢,这很有帮助,我现在明白了。我已经完成了这项工作,但是我遇到了一个问题,即旋转(尽管现在围绕正确的点)并没有“粘”在用户的手指上。我已经在上面添加了我的方法,你能看到它可能有什么问题吗?我正在平移多少与它正在移动多少的比率是关闭的。
      • 非常感谢您的精彩解释...我的请求是请您给我们一个完整的代码和少量演示..??? @大卫
      【解决方案3】:

      您需要做的是在平移时,在 pangesturerecognizer 的处理程序中,您需要对正在平移的视图应用旋转变换。喜欢self.SomeView.transform = CGAffineTransformMakeRotation(some rotation)。您需要对要应用的旋转量进行一些计算。设置中心也是如此。

      【讨论】:

      • 你能稍微扩展一下吗?我正在努力计算用户触摸手指时将使用的变量。
      • 真的不知道任何公式,但我想到的是,当您从右上角向内平移时,您可能需要对按测量角度平移的视图应用旋转变换在说当前点和前一点之间。不确定我是否清楚地解释了这一点,但是假设您已经从 A 点平移到 B 点,如果您要将它们连接到原点,则两点之间的角度是您可能需要旋转视图的角度。
      猜你喜欢
      • 2013-09-17
      • 1970-01-01
      • 2010-10-11
      • 2014-03-12
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 2022-09-26
      • 1970-01-01
      相关资源
      最近更新 更多