Pinch Zoom смещает изображение в самый левый угол на iPad в iOS?

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

Мой код:

-(void)viewDidLoad
{
UIPinchGestureRecognizer *pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
            [self.zoom_image addGestureRecognizer:pinch];
            panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveImage:)];
            [panGesture setMinimumNumberOfTouches:1];
            [panGesture setMaximumNumberOfTouches:1];
            [self.zoom_image addGestureRecognizer:panGesture];

            img_center_x = self.zoom_image.center.x;
            img_center_y = self.zoom_image.center.y;

}

-(void)handlePinch:(UIPinchGestureRecognizer*)sender
{
    NSLog(@"latscale = %f",mLastScale);
    mCurrentScale += [sender scale] - mLastScale;
    mLastScale = [sender scale];
    NSLog(@"before ceneter x %f",img_center_x);
    NSLog(@"before ceneter x %f",img_center_y);
    CGPoint img_center = CGPointMake(img_center_x, img_center_y);
    self.zoom_image.center = img_center;
    if (sender.state == UIGestureRecognizerStateEnded)
    {
      mLastScale = 1.0;
    }
    if(mCurrentScale<1.0)
    {
        mCurrentScale=1.0;
    }
    if(mCurrentScale>3.0)
    {
        mCurrentScale=3.0;
    }
    CGAffineTransform currentTransform = CGAffineTransformIdentity;
    CGAffineTransform newTransform = CGAffineTransformScale(currentTransform,mCurrentScale, mCurrentScale);
    self.zoom_image.transform = newTransform;

}

Жест панорамирования

 UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveImage:)];
            [panGesture setMinimumNumberOfTouches:1];
            [panGesture setMaximumNumberOfTouches:1];
            [self.zoom_image addGestureRecognizer:panGesture];

move image:

- (void)moveImage:(UIPanGestureRecognizer *)recognizer
{
    CGPoint translation = [recognizer translationInView:self.zoom_image];
    CGPoint location = [recognizer locationInView:self.view];
    CGPoint initial=CGPointZero;
    NSLog(@"%f\n%f",translation.x,translation.y);
    NSLog(@"%f",self.zoom_image.frame.origin.y);
    CGPoint finalpoint = CGPointMake(self.zoom_image.center.x + translation.x, self.zoom_image.center.y+ translation.y);
    NSLog(@"%f",finalpoint.y);
    //limit the boundary
    if(recognizer.state==UIGestureRecognizerStateChanged)
    {
        if ((self.zoom_image.frame.origin.x>0 && translation.x > 0) || (self.zoom_image.frame.origin.x + self.zoom_image.frame.size.width<=self.view.frame.size.width && translation.x < 0))
            finalpoint.x = self.zoom_image.center.x;

        if ((self.zoom_image.frame.origin.y>100 && translation.y > 0) || (self.zoom_image.frame.origin.y + self.zoom_image.frame.size.height<=self.view.frame.size.height && translation.y < 0))
            finalpoint.y = self.zoom_image.center.y;
        //set final position
        NSLog(@"%f",finalpoint.y);
        self.zoom_image.center = finalpoint;
        [recognizer setTranslation:initial inView:self.zoom_image];
    }
}

person TechChain    schedule 30.10.2015    source источник


Ответы (1)


Вот возможное решение.

• Я переименовал ваш zoom_image в contentView, потому что этот класс может манипулировать любым представлением, а не только изображениями.

• Я удалил связанные тесты и оставил шкалу в (0,01 - 10,0)

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

Есть еще много чего улучшить, но главный принцип здесь :)

Интерфейс (такие свойства, как minScale, maxScale, minMargin и т. д., еще предстоит добавить — почему бы не делегат)

@interface PinchViewController : UIViewController

@property(nonatomic,strong) IBOutlet UIView* contentView;

@end

Реализация

@implementation PinchViewController
{
    CGPoint translation;
    CGFloat scale;

    CGAffineTransform scaleTransform;
    CGAffineTransform translateTransform;

    CGPoint     previousTranslation;
    CGFloat     previousScale;
    NSUInteger  previousNumTouches;
}

-(void)viewDidLoad
{
    scale = 1.0f;
    scaleTransform = CGAffineTransformIdentity;
    translateTransform = CGAffineTransformIdentity;
    previousTranslation = CGPointZero;
    previousNumTouches = 0;

    UIPinchGestureRecognizer *pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
    [self.view addGestureRecognizer:pinch];

    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [panGesture setMinimumNumberOfTouches:1];
    [panGesture setMaximumNumberOfTouches:1];
    [self.view addGestureRecognizer:panGesture];

}

-(void)handlePinch:(UIPinchGestureRecognizer*)recognizer
{
    // 1 - find pinch center
    CGPoint mid = [self computePinchCenter:recognizer];
    mid.x-= recognizer.view.bounds.size.width / 2.0f;
    mid.y-= recognizer.view.bounds.size.height / 2.0f;

    // 2 - compute deltas
    NSUInteger numTouches = recognizer.numberOfTouches;
    if ( (recognizer.state==UIGestureRecognizerStateBegan)  || ( previousNumTouches != numTouches ) ) {
        previousScale = recognizer.scale;
        previousTranslation = mid;
        previousNumTouches = numTouches;
    }

    CGFloat deltaScale = ( recognizer.scale - previousScale ) * scale;
    previousScale = recognizer.scale;

    CGPoint deltaTranslation = CGPointMake(mid.x-previousTranslation.x, mid.y-previousTranslation.y);
    previousTranslation = mid;

    deltaTranslation.x/=scale;
    deltaTranslation.y/=scale;

    // 3 - apply
    scale+=deltaScale;

    if (scale<0.01) scale = 0.01; else if (scale>10) scale = 10;

    scaleTransform = CGAffineTransformMakeScale(scale, scale);
    [self translateBy:deltaTranslation];

    NSLog(@"Translation : %.2f,%.2f - Scale Center : %.2f,%.2f - Scale : %.2f",deltaTranslation.x,deltaTranslation.y,mid.x,mid.y,scale);
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    if (recognizer.state==UIGestureRecognizerStateBegan) previousTranslation = CGPointZero;
    CGPoint recognizerTranslation = [recognizer translationInView:self.contentView];
    CGPoint deltaTranslation = CGPointMake(recognizerTranslation.x - previousTranslation.x,recognizerTranslation.y - previousTranslation.y);
    previousTranslation = recognizerTranslation;
    [self translateBy:deltaTranslation];

    NSLog(@"Translation : %.2f,%.2f - Scale : %.2f",deltaTranslation.x,deltaTranslation.y,scale);
}


-(void)translateBy:(CGPoint)delta
{
    translation.x+=delta.x;
    translation.y+=delta.y;
    translateTransform = CGAffineTransformMakeTranslation(translation.x,translation.y);
    self.contentView.transform = CGAffineTransformConcat(translateTransform,scaleTransform);
}

-(CGPoint)computePinchCenter:(UIPinchGestureRecognizer*)recognizer
{
    // 1 - handle up to 3 touches
    NSUInteger numTouches = recognizer.numberOfTouches;
    if (numTouches>3) numTouches = 3;

    // 2 - Find fingers middle point - with (0,0) being the center of the view
    CGPoint pt1,pt2,pt3,mid;
    switch (numTouches) {
        case 3:
            pt3 = [recognizer locationOfTouch:2 inView:recognizer.view];
        case 2:
            pt2 = [recognizer locationOfTouch:1 inView:recognizer.view];
        case 1:
            pt1 = [recognizer locationOfTouch:0 inView:recognizer.view];
    }
    switch (numTouches) {
        case 3:
            mid = CGPointMake( ( ( pt1.x + pt2.x ) / 2.0f + pt3.x ) / 2.0f, ( ( pt1.y + pt2.y ) / 2.0f + pt3.y ) / 2.0f );
            break;
        case 2:
            mid = CGPointMake( ( pt1.x + pt2.x ) / 2.0f, ( pt1.y + pt2.y ) / 2.0f  );
            break;
        case 1:
            mid = CGPointMake( pt1.x, pt1.y);
            break;
    }
    return mid;
}

@end

Надеюсь, это поможет :) Ура

person Moose    schedule 06.11.2015
comment
да… Это было быстрое предположение. Я спал на нем. Я редактирую и заменяю возможным способом сделать это. - person Moose; 07.11.2015
comment
Да - первое решение было быстрым предположением, но не работало. Отредактированный ответ работает и по-прежнему допускает множество улучшений. - person Moose; 07.11.2015
comment
какие улучшения? - person TechChain; 07.11.2015
comment
установите ограничения с помощью таких свойств, как minScale, maxScale... Алгоритм сжатия уже работает достаточно хорошо, но центр пальцев не полностью неподвижен во время масштабирования. Должен, но я не могу тратить на это больше времени :) - person Moose; 07.11.2015
comment
Кстати, я голосую за ваш вопрос, потому что это был интересный вызов ;) Увидимся! - person Moose; 07.11.2015
comment
Голосовать было намного проще, чем писать рабочий код, чтобы ответить вам @deepakkumar... - person Moose; 09.11.2015
comment
Вы должны были сказать это раньше... На самом деле, это работает очень хорошо. Я тестировал его на iPhone 5 iOS 9.x и iPad iOS 8.x. Попробуйте проект: drive.google.com/open?id=0B88aMtNA0z2aWVBIbGZGdVhpdWM - person Moose; 09.11.2015
comment
он перемещает изображение, даже если изображение не увеличено. Пожалуйста, скажите, почему - person TechChain; 09.11.2015
comment
Я говорю вам, почему. Изображение не перемещается, когда его размер меньше размера экрана. В данном случае он центрирован. Если изображение больше, его можно переместить, даже если масштаб один. Но вы находитесь на stackoverflow, платформе для совместной работы. Мы не должны предлагать вам готовый продукт, даже за вознаграждение (которое вы не даете), но предложить вам наилучший ключ к достижению вашей цели. Если вы предпочитаете, чтобы изображение было неподвижным, когда масштаб равен единице, даже если оно больше экрана, адаптируйте его к своим потребностям. База правильная. - person Moose; 09.11.2015
comment
Просто добавьте возврат if (scale‹=0.0f); в начале метода translateBy блокировать перевод, когда масштаб меньше 1 - person Moose; 09.11.2015
comment
Вы загрузили мой пример проекта? Я не посылал вам что-то, что не работает. Я сказал вам, что это было проверено на двух устройствах. - person Moose; 10.11.2015
comment
ваш код диска Google требует доступа. поэтому, пожалуйста, сделайте его общедоступным. я не могу его загрузить - person TechChain; 10.11.2015
comment
Извините ;) - drive.google.com/file/d/0B88aMtNA0z2aWVBIbGZGdVhpdWM/ - person Moose; 10.11.2015
comment
Это работает, но я могу уменьшить масштаб до минимального уровня, чего не должно происходить. - person TechChain; 10.11.2015
comment
Просто измените лимиты. Я также сказал вам, что это может быть улучшено. Просто измените строку, если (масштаб‹0,01) масштаб = 0,01; иначе если (шкала>10) шкала = 10; изменить ограничения... - person Moose; 10.11.2015
comment
Это рабочая основа. Оттуда вы должны быть в состоянии адаптировать его к вашим потребностям без больших изменений. - person Moose; 10.11.2015
comment
Это в коде, который я вам отправил, в методе handlePinch. Вы можете установить все действия по сжатию в методе handlePinch, а все действия по переводу — в методе translateBy, но не в методе handlePan, потому что при сжатии вы также можете панорамировать изображение. - person Moose; 10.11.2015
comment
Пожалуйста, опубликуйте точный код для преодоления этого поведения. Я не могу понять - person TechChain; 10.11.2015
comment
Давайте продолжим это обсуждение в чате. - person Moose; 10.11.2015