Использование PinchGesture; как я могу увеличить, где пальцы пользователя на самом деле"ущипнуть"?

я реализовал UIPinchGestureRecognizer на UIImageView в моем приложении, однако независимо от того, где я сжимаю изображение, оно, похоже, приближается к тому же месту. Кто-нибудь знает, как я могу увеличить масштаб до того, где пользователь фактически "зажимает"? См. код ниже.

ViewController.м

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

   recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
   recognizer.scale = 1; 

 }

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
{
    BOOL shouldReceiveTouch = YES;

    if (gestureRecognizer == tap) {
        shouldReceiveTouch = (touch.view == featureImage);
    }
    return shouldReceiveTouch;
}

3 ответов


масштабное преобразование оставляет нетронутым начало координат (0, 0). Поэтому, чтобы масштабировать вид вокруг определенной точки, вы должны сначала перевести эту точку в начало координат, затем применить масштаб, а затем перевести обратно.

- (IBAction)pinchGestureDidFire:(UIPinchGestureRecognizer *)pinch {

во-первых, мы получаем вид ущипнули.

    UIView *pinchView = pinch.view;

чтобы вычислить центр щепотки, нам понадобится середина границ вида, поэтому мы тоже получим границы:

    CGRect bounds = pinchView.bounds;

центр основан на центроиде касаний щипка, что мы получаем таким образом:

    CGPoint pinchCenter = [pinch locationInView:pinchView];

но нам действительно нужно смещение щепотки относительно центра представления, потому что преобразование представления относительно центра представления по умолчанию. (Вы можете изменить это, изменив представление layer.anchorPoint.)

    pinchCenter.x -= CGRectGetMidX(bounds);
    pinchCenter.y -= CGRectGetMidY(bounds);

теперь мы можем обновить вид преобразования. Сначала мы получаем его текущее преобразование:

    CGAffineTransform transform = pinchView.transform;

затем мы обновляем его, чтобы перевести центр Пинча в начало:

    transform = CGAffineTransformTranslate(transform, pinchCenter.x, pinchCenter.y);

теперь мы можно применить шкалу:

    CGFloat scale = pinch.scale;
    transform = CGAffineTransformScale(transform, scale, scale);

затем мы переводим взгляд назад:

    transform = CGAffineTransformTranslate(transform, -pinchCenter.x, -pinchCenter.y);

теперь мы можем обновить представление с измененными преобразования:

    pinchView.transform = transform;

наконец, мы сбрасываем шкалу распознавания жестов, так как мы применили текущую шкалу:

    pinch.scale = 1.0;
}

демо:

pinch scale

обратите внимание, что в симуляторе вы можете удерживать опцию (alt) для жеста щепотки. Удержание shift (при удержании опции) перемещает два штрихи вместе.

вот код, все вместе копировать/вставить:

- (IBAction)pinchGestureDidFire:(UIPinchGestureRecognizer *)pinch {
    UIView *pinchView = pinch.view;
    CGRect bounds = pinchView.bounds;
    CGPoint pinchCenter = [pinch locationInView:pinchView];
    pinchCenter.x -= CGRectGetMidX(bounds);
    pinchCenter.y -= CGRectGetMidY(bounds);
    CGAffineTransform transform = pinchView.transform;
    transform = CGAffineTransformTranslate(transform, pinchCenter.x, pinchCenter.y);
    CGFloat scale = pinch.scale;
    transform = CGAffineTransformScale(transform, scale, scale);
    transform = CGAffineTransformTranslate(transform, -pinchCenter.x, -pinchCenter.y);
    pinchView.transform = transform;
    pinch.scale = 1.0;
}

быстрая реализация ответа Роба:

@objc private func pinchHandler(gesture: UIPinchGestureRecognizer) {
    if let view = gesture.view {

        switch gesture.state {
        case .changed:
            let pinchCenter = CGPoint(x: gesture.location(in: view).x - view.bounds.midX,
                                      y: gesture.location(in: view).y - view.bounds.midY)
            let transform = view.transform.translatedBy(x: pinchCenter.x, y: pinchCenter.y)
                                            .scaledBy(x: gesture.scale, y: gesture.scale)
                                            .translatedBy(x: -pinchCenter.x, y: -pinchCenter.y)
            view.transform = transform
            gesture.scale = 1
        case .ended:
            // Nice animation to scale down when releasing the pinch.
            // OPTIONAL
            UIView.animate(withDuration: 0.2, animations: {
                view.transform = CGAffineTransform.identity
            })
        default:
            return
        }


    }
}

вы можете просто добавить scrollView и в scrollView добавить imageView, как показано ниже,

![ImageView on top of scrollView][1]

некоторые проблемы с загрузкой изображения, поэтому проверьте изображение на этом ссылке

затем вы можете создать свойство IBOutlet scrollView и imageView и подключить его соответственно. Позже добавьте эти строки в метод viewDidAppear,

_scrollView.maximumZoomScale = 10.0;        //Maximum Zoom
_scrollView.minimumZoomScale = minimumScale;   //Minimum Zoom

добавить ниже метод,

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
   return _imageView;
}

Итак, теперь вы получите эффекты увеличения/уменьшения масштаба и максимальный / минимальный предел масштабирования, установленный u. Меньший код вместе с достижением цели ur.