如何在捏合手势(多次捏合)上准确放大特定点?

时间:2014-05-01 02:55:11

标签: ios objective-c matrix uigesturerecognizer transformation

我正在尝试缩放iOS应用程序中的四元组。它需要不是基于四边形的中心进行缩放,而是基于捏的质心。

我能够正确地执行此操作 - 但仅适用于第一个捏合手势。在随后的捏合手势中,它可以工作,但它会稍微漂移并且看起来不太准确。我无法弄清楚该怎么做。

围绕这个问题有几个问题,而且我已经完成了大部分问题,如果不是全部的话。他们都没有准确地解决我的问题。

另请注意,我正在缩放和翻译四边形(渲染为GLKView),而不是视图本身。我见过的大多数解决方案都是直接转换视图。

以下是捏合手势和处理的代码: 首先在viewDidLoad中:

UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc]
                                             initWithTarget:self action:@selector(respondToPinchGesture:)];
pinchRecognizer.cancelsTouchesInView = YES;
pinchRecognizer.delaysTouchesEnded = NO;
[glView addGestureRecognizer:pinchRecognizer];

其中glView是GLKView对象。 和处理程序:

- (IBAction)respondToPinchGesture:(UIPinchGestureRecognizer *)recognizer{

    if (recognizer.state == UIGestureRecognizerStateEnded || [recognizer numberOfTouches] < 2) return;

    if (recognizer.state == UIGestureRecognizerStateBegan) {
        point = [recognizer locationInView:glView];
        point.x *= glView.contentScaleFactor;
        point.y *= glView.contentScaleFactor;
        point.y = height - point.y;

        anchor = GLKVector3Make(point.x, point.y, 0);
        lastScale = 1.0;
    }

    if (fabs(recognizer.scale - lastScale) > 0.01){

        GLfloat scale = 1.0 - (lastScale - recognizer.scale);
        lastScale = recognizer.scale;

        new_anchor_point = anchor;
        new_anchor_point = GLKVector3MultiplyScalar(new_anchor_point, scale);
        GLKVector3 translate = GLKVector3Subtract(anchor, new_anchor_point);

        path.transform = GLKMatrix4TranslateWithVector3(path.transform, translate);
        path.transform = GLKMatrix4Scale(path.transform, scale, scale, 0);

        cumulative_translate = GLKVector3Add(cumulative_translate, translate);
    }

}

任何指针都表示赞赏。我是2天,甚至一个模糊的建议可能会有所帮助。

2 个答案:

答案 0 :(得分:0)

你必须

  • 记住上一次转化矩阵在RecognizerStateBegan上,
  • 为缩放缩放构建新的变换矩阵,假设视图或对象之前没有被转换过。
  • 然后,将两个矩阵连接在一起。这将是您转换对象或视图的最终矩阵。

答案 1 :(得分:-1)

我设法使用以下方法解决了这个问题:

-(GLKVector3)get_touch_point_on_view:(UIGestureRecognizer *)recognizer{
    CGRect bounds = [glView bounds];
    CGPoint point = [recognizer locationInView:glView];
    point.y = bounds.size.height - point.y;
    return GLKVector3Make((point.x * glView.contentScaleFactor - total_translation.x)/total_scale,
                                   (point.y * glView.contentScaleFactor - total_translation.y)/total_scale, 0);
}
- (void)respondToPinchGesture:(UIPinchGestureRecognizer *)recognizer{
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        lastScale = 1.0;
    }

    [self get_touch_point_on_view:recognizer];

    if (fabs(recognizer.scale - lastScale) > 0.01){

        GLfloat scale = 1.0 - (lastScale - recognizer.scale);
        lastScale = recognizer.scale;
        total_scale *= scale;

        path.transform = GLKMatrix4TranslateWithVector3(path.transform, centroid);
        path.transform = GLKMatrix4Scale(path.transform, scale, scale, 0);
        path.transform = GLKMatrix4TranslateWithVector3(path.transform, GLKVector3Negate(centroid));
        total_translation = [self get_total_translation];

    }
}