Pinch zoom shifting image to most left corner on i

2019-06-15 21:25发布

I have a image in iOS. I have added pinch gesture on the image when i pinch the image it shifted to top left corner. I have also added pan gesture on image. When an image is zoomed then i am scrolling the image in every direction for that purpose i have added the pan gesture into the image.

My code is :

-(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;

}

Pan gesture

 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];
    }
}

1条回答
【Aperson】
2楼-- · 2019-06-15 21:43

Here is a possible solution.

• I've renamed your zoom_image by contentView, because this class can manipulate any view, not only images.

• I've removed the bound tests, and let the scale be in ( 0.01 - 10.0 )

• The pinch handle up to three fingers, and also acts as pan. Number of touches can be changed without interrupting the pinch.

There is still many things to improve, but the main principle is here :)

Interface ( properties like minScale,maxScale, minMargin and so are still to be added - why not a delegate )

@interface PinchViewController : UIViewController

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

@end

Implementation

@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

Hope it will help :) Cheers

查看更多
登录 后发表回答