Как плавно анимировать CGAffineTransform при выполнении жеста перетаскивания

Я отлично разбираюсь в различных способах обнаружения жестов перетаскивания (в настоящее время я использую UIPanGestureRecognizer), но мое понимание преобразований ограничено, поэтому я не уверен, возможно ли/как это возможно. По сути, я хочу, чтобы преобразование масштабирования применялось к UIView в том же темпе (из-за отсутствия лучшего слова), когда пользователь выполняет жест перетаскивания в другом месте экрана. Другими словами, когда пользователь перетаскивает вверх, я хочу, чтобы размер моего преобразующего UIView увеличивался пропорционально положению этого жеста, и если пользователь затем начинает перетаскивать вниз, он должен начать пропорционально уменьшаться.

Надеюсь, это имеет смысл. В качестве фиктивного примера просто представьте ползунок, который можно настроить для изменения размера UIView в режиме реального времени. Есть ли хороший способ сделать такие добавочные обновления постоянного размера с помощью CGAffineTransform?


person cowfaboo    schedule 17.04.2013    source источник


Ответы (2)


В обработчике жестов панорамирования вы просто берете translationInView или locationInView, вычисляете масштаб на основе этого, а затем соответствующим образом обновляете преобразование. Например:

- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static CGAffineTransform originalTransform;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalTransform = self.viewToScale.transform;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [gesture translationInView:gesture.view];
        CGFloat scale = 1.0 - translation.y / 160.0;
        self.viewToScale.transform = CGAffineTransformScale(originalTransform, scale, scale);
    }
}

Вы можете поиграть с расчетом scale в зависимости от того, что именно вы хотите сделать, но, надеюсь, вы поняли идею.

Лично я бы предпочел использовать распознаватель жестов щипка для изменения размера (это пользовательский интерфейс, на котором обучены пользователи, он дает вам коэффициент scale прямо из коробки и т. д.), но все, что работает для вас. Если бы вы использовали распознаватель жестов щипка, это могло бы выглядеть так:

- (void)handlePinch:(UIPinchGestureRecognizer *)gesture
{
    static CGAffineTransform originalTransform;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalTransform = self.viewToScale.transform;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        self.viewToScale.transform = CGAffineTransformScale(originalTransform, gesture.scale, gesture.scale);
    }
}
person Rob    schedule 17.04.2013
comment
Отлично - недостающим звеном для меня была идея всегда применять преобразования к тому, что вы назвали originalTransform, так что я уже в пути. Я согласен с тем, что в большинстве случаев жест щипка имеет смысл для масштабирования. В данном случае, однако, я играю с творческими способами перехода между представлениями, и этот масштаб на самом деле является просто причудливым побочным эффектом во время перехода, вызванного перетаскиванием. Большое спасибо за обстоятельный ответ! - person cowfaboo; 18.04.2013

Я обнаружил, что лучший подход — использовать locationInView, чтобы вы могли приравнять смещение местоположения в пикселях к масштабу. Например, если круг расположен в центре вида:

func dragDot(recognizer: UIPanGestureRecognizer) {

    let locationX = recognizer.location(in: self.view).x

    // Expand and contract the circle
    let locationXOffset = locationX - self.view.center.x

    // We need scale to be 1 when locationXOffset = circle radius
    let scale: CGFloat = locationXOffset / (self.widthOfCircle / 2)

    self.ring.transform = CGAffineTransform(scaleX: scale, y: scale)
}

Если круг не находится в центре изображения, замените self.view.center.x начальным местоположением круга.

Этот метод будет работать на всех устройствах и разрешениях экрана и позволит избежать необходимости калибровки постоянного

person Tom    schedule 28.06.2017
comment
вы должны серьезно упомянуть: что такое widthOfCircle? иначе не ждите голосов.. - person Yash Bedi; 31.08.2017