【问题标题】:How do I map the x co-ordinate of a pan gesture to the rotation of cube?如何将平移手势的 x 坐标映射到立方体的旋转?
【发布时间】:2013-07-20 05:46:12
【问题描述】:

我正在开发一个 iPhone 应用程序,其中主要视图在立方体的表面上呈现给用户。用户通过平移手势旋转立方体来切换视图。

为了实现这一点,我正在使用来自this GitHub project 的 GKLCubeController 类。

在向立方体添加视图和旋转方面,它工作正常。然而,立方体的角度旋转并没有正确映射到手指在屏幕上平移时的当前x 位置。

问题在于立方体旋转滞后于手指移动约 ½ 秒,这使得立方体感觉“沉重”,如 this short screencast 所示。

处理旋转的代码如下所示:

-(void)panHandler:(UIPanGestureRecognizer*)panner{
    CGPoint translatedPoint = [panner translationInView:self.view.window];
    CGFloat halfWidth = self.view.bounds.size.width / 2.0;
    //    save our starting points
    if([panner state] == UIGestureRecognizerStateBegan) {
        startingX = translatedPoint.x;
        if (!transformLayer) {
            transformLayer = [[CATransformLayer alloc] init];
            transformLayer.frame = self.view.layer.bounds;

            for (UIView *viewToTranslate in views) {
                [viewToTranslate removeFromSuperview];
                [transformLayer addSublayer:viewToTranslate.layer];
            }
            //        add in this new layer
            [self.view.layer addSublayer:transformLayer];
        }
    } else if([panner state] == UIGestureRecognizerStateEnded) {
       ...
    } else {
        //        instantly adjust our transformation layer
        CATransform3D transform = CATransform3DIdentity;
        transform.m34 = kPerspective;
        double percentageOfWidth = (translatedPoint.x - startingX) / self.view.frame.size.width;
        transform = CATransform3DTranslate(transform, 0, 0, -halfWidth);
        double adjustmentAngle = percentageOfWidth * M_PI_2 + startingAngle;
        transform = CATransform3DRotate(transform, adjustmentAngle, 0, 1, 0);
        transform = CATransform3DTranslate(transform, 0, 0, halfWidth);
        transformLayer.transform = transform;
        finishingAngle = adjustmentAngle;
    }
}

我怀疑问题与将UIPanGestureRecognizer translationInView: 返回的CGPoint.x 转换为旋转角度有关。任何人都可以确认是否是这种情况,并建议将触摸位置x 映射到立方体的旋转的正确数学应该是什么,以便立方体边缘在它在屏幕上平移时跟踪手指运动?

【问题讨论】:

    标签: ios objective-c cocoa 3d


    【解决方案1】:

    这里有两个问题:

    1. 这里的主要性能问题是此类执行立方体侧面变换的方式。它给立方体的每一面都进行了复杂的变换,然后当你拖动立方体时,它会占用立方体的相关边,将它们添加到CATransformLayer,并在该层上执行复杂的变换(因此,当您查看立方体的各个侧面时,您正在执行变换的变换)。

      我提取了 CATransformLayer 逻辑,并更新了各个方面的转换,它的响应速度显着提高。

      顺便说一句,当您为旋转立方体的释放设置动画时,您可能仍希望使用类似CATransformLayer 的逻辑,因为这是同步立方体各个侧面动画的绝佳方式(否则在动画过程中,立方体的侧面会有一些分离)。但是在拖拽的时候,对性能的影响太大了。

      随着您继续完善这一点,可能还可以进行其他优化,但我的测试表明,在复杂的转换上去掉转换会对性能产生巨大影响。

      顺便说一句,请务必在设备上进行测试,而不是在模拟器上进行测试,因为模拟器的图形性能与设备的图形性能大不相同。

    2. 可能导致响应速度出现轻微初始延迟的一个次要因素可能是 UIPanGestureRecognizer 中的固有延迟(它会在将手势识别为平移之前寻找一定的移动量,以便其他手势,例如点击和如果合适,like 可以触发)。这是一个适度的延迟,只是性能问题的一小部分,但为了获得最快的响应时间,您可能不想使用UIPanGestureRecognizer。要么继承你自己的子类,要么使用 UILongPressGestureRecognizer0.0minimumPressDuration,你可以获得对手势的即时响应。

      您会看到它对运动的反应更快(但这也是一种与其他人不兼容的手势,如果您在视图中有点击手势或类似的手势,它们将不会被触发)。

    【讨论】:

    • 非常感谢您的详细回复!我刚刚尝试了使用UILongPressGestureRecognizerminimumPressDuration = 0.0 的技术,并且有轻微的改进,但并不大。我做了一个测试,只是用UIPanGestureRecognizer 在屏幕上移动了一圈,实际上与旋转立方体时的开销延迟相比,延迟是最小的。因此,我尝试了另一个测试,只绘制了立方体的一侧。这显示为here,如您所见,仍然存在延迟,例如您没有得到使用 Wea​​therCube 应用程序。还有其他想法吗?
    • 我还应该补充一点,我在设备上进行了测试,在这种情况下,设备(iPhone 5)和模拟器性能之间的差异可以忽略不计。
    • @JamieBullock 嗯。好吧,我自己做了一个立方体效果的测试,它保持得很好(即使在我的测试 iPhone 3GS 上)。关于GKCubeController 的实现,唯一让我印象深刻的是它将所有边添加到某个层并旋转它(而我只旋转在给定时刻可见的两个边)。也许还有其他问题。我明天去看看。
    • @JamieBullock 我测试了该项目并确认了性能问题:问题是它有四个视图具有复杂的层变换,然后将它们添加到新的 CATransformLayer 并在那(因此对变换进行四次变换)。当我提取该代码并更新单独的变换时,立方体的每个可见侧都有一个变换,它快得多。在将它们动画化时使用超级层技巧很有用(它可以很好地保持一切同步),但是在尝试跟踪手势时,它的计算效率太低了。
    • 顺便说一下,我尝试在此处解决其中的几个性能问题:github.com/robertmryan/GKLCubeViewController
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 2020-05-22
    相关资源
    最近更新 更多