Тот же CGAffineTransform другой якорь - PullRequest
2 голосов
/ 23 ноября 2011

У меня 1 просмотр с 2 подпредставлениями.Один из них в 10 раз больше другого.У меня есть распознаватель жестов для большого (который сверху).

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

Надеюсь, я объясню сам.Вот код:

- (void)twoFingerPinch:(UIPinchGestureRecognizer *)gestureRecognizer
{    
    //this changes the anchor point of "big" without moving it
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {    

        CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
        float scale = sqrt(transform.a*transform.a+transform.c*transform.c);

        //this transforms "big"
        [gestureRecognizer view].transform = transform;

        //anchor point location in little view
        CGPoint pivote = [gestureRecognizer locationInView:little];

        CGAffineTransform transform_t = CGAffineTransformConcat(CGAffineTransformMakeTranslation(-pivote.x, -pivote.y), transform);
        transform_t = CGAffineTransformConcat(transform_t, CGAffineTransformMakeTranslation(pivote.x, pivote.y));

        little.transform = transform_t;
    }
    [gestureRecognizer setScale:1];
}

Но это не работает, маленький вид продолжает прыгать и сходить с ума.

РЕДАКТИРОВАТЬ: Подробнее.

Хорошо, этоВот диаграмма: diagram

Красный квадрат - это большой вид, темный - маленький.Пунктирный квадрат - это основной вид.

Линия: [self AdjustAnchorPointForGestureRecognizer: gestRecognizer];изменяет точку привязки больших видов на центр жеста щепотки.Это работает.

Когда я масштабирую большой вид, малый вид должен масштабироваться на ту же величину и перемещаться, чтобы он центрировался на большом виде, как сейчас.То есть он должен масштабироваться с той же точкой привязки, что и большой вид.

Я хотел бы сохранить эти преобразования в небольшом виде в CGAffineTransform, если это возможно.

Ответы [ 2 ]

2 голосов
/ 24 ноября 2011

Хорошо, я наконец нашел это. Я не знаю, является ли это лучшим решением, но оно работает.

- (void)twoFingerPinch:(UIPinchGestureRecognizer *)gestureRecognizer
{    
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {    

        CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
        float scale = sqrt(transform.a*transform.a+transform.c*transform.c);
        if((scale>0.1)&&(scale<20)) {

            [gestureRecognizer view].transform = transform;

            CGPoint anchor = [gestureRecognizer locationInView:little];
            anchor = CGPointMake(anchor.x - little.bounds.size.width/2, anchor.y-little.bounds.size.height/2);

            CGAffineTransform affineMatrix = little.transform;
            affineMatrix = CGAffineTransformTranslate(affineMatrix, anchor.x, anchor.y);
            affineMatrix = CGAffineTransformScale(affineMatrix, [gestureRecognizer scale], [gestureRecognizer scale]);
            affineMatrix = CGAffineTransformTranslate(affineMatrix, -anchor.x, -anchor.y);        
            little.transform = affineMatrix;    

            [eagleView setTransform:little.transform];    
            [gestureRecognizer setScale:1];
        }

    }
}

Эта строка eaglView - реальная причина, по которой мне нужен CGAffineTransform, и я не могу изменить привязку. Я отправляю его в OpenGL, чтобы изменить матрицу преобразования вида модели.

Теперь он отлично работает с 3-мя преобразованиями (вращение, масштабирование, преобразование) одновременно благодаря обратной связи с пользователем.

EDIT

Небольшое замечание: кажется, что, когда я перемещаю представление слишком быстро, eaglView и UIView не синхронизируются. Поэтому я не применяю преобразования непосредственно к UIViews, я применяю их с информацией из eaglView. Как это:

- (void)twoFingerPinch:(UIPinchGestureRecognizer *)gestureRecognizer
{    
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {    

        CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
        float scale = sqrt(transform.a*transform.a+transform.c*transform.c);
        if((scale>0.1)&&(scale<20)) {

            //[gestureRecognizer view].transform = transform;

            CGPoint anchor = [gestureRecognizer locationInView:little];
            anchor = CGPointMake(anchor.x - little.bounds.size.width/2, anchor.y-little.bounds.size.height/2);

            CGAffineTransform affineMatrix = little.transform;
            affineMatrix = CGAffineTransformTranslate(affineMatrix, anchor.x, anchor.y);
            affineMatrix = CGAffineTransformScale(affineMatrix, [gestureRecognizer scale], [gestureRecognizer scale]);
            affineMatrix = CGAffineTransformTranslate(affineMatrix, -anchor.x, -anchor.y);        
            //little.transform = affineMatrix;    

            [eagleView setTransform:affineMatrix];    
            [gestureRecognizer setScale:1];

            CGAffineTransform transform = CGAffineTransformMakeRotation(eaglView.myRotation*M_PI/180);
            transform = CGAffineTransformConcat(CGAffineTransformMakeScale(eaglView.myScale, eaglView.myScale), transform);
            transform = CGAffineTransformConcat(transform, CGAffineTransformMakeTranslation(eaglView.myTranslate.x, -eaglView.myTranslate.y));    
            little.transform = transform;
            big.transform = transform;
        }

    }
}
0 голосов
/ 23 ноября 2011

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

CGRect frame = little.frame; // Returns the frame based on the current transform
frame.origin.x = (frame.origin.x - pivot.x) * gestureRecognizer.scale;
frame.origin.y = (frame.origin.y - pivot.y) * gestureRecognizer.scale;
frame.width = frame.width * gestureRecognizer.scale;
frame.height = frame.height * gestureRecognizer.scale;

Затем обновите преобразование. Лично я бы сделал это, основываясь на реальной позиции представления, а не на преобразовании текущего преобразования - мне легче думать. Так, например:

little.transform = CGAffineTransformIndentity; // Remove the current transform
CGRect orgFrame = little.frame
CGFloat scale = frame.width / orgFrame.size.width;
CGAffineTransform t = CGAffineTransformMakeScale(scale, scale);
t = CGAffineTransformConcat(t, CGAffineTransformMakeTranslation(newFrame.origin.x - frame.origin.x, newFrame.origin.y - frame.origin.y));
little.transform = t;

Обратите внимание, что я только что набрал код на макушке, чтобы дать вам и идею. Это потребует тестирования и отладки!

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

Тим

...