如何在用户捏屏幕时放大/缩小UIImage对象?

问题描述:

我想放大/缩小UIImage对象,当用户在我的应用程序上执行标准捏合动作。我正在使用UIImageView来显示我的图像,如果这些细节有任何帮助。如何在用户捏屏幕时放大/缩小UIImage对象?

我想弄清楚如何做到这一点,但迄今没有这样的运气。

任何线索?

另一种简单的方法来做到这一点是把你的UIImageViewUIScrollViewAs I describe here,您需要将滚动视图的contentSize设置为与您的UIImageView's大小相同。将您的控制器实例设置为滚动视图的代表,并实施viewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale:方法以允许捏缩放和图像平移。这实际上就是Ben的解决方案所做的事情,只是以轻量级的方式,因为您没有完整的Web视图的开销。

您可能遇到的一个问题是滚动视图中的缩放比例是以应用于图像的转换形式出现的。这可能导致高变焦系数模糊。对于可以重绘的内容,您可以按照我的建议here在捏合手势完成后提供更清晰的显示。 hniels的解决方案可以用来重新调整图像。

+2

请确保您更改maximumZoomScale和/或minimumZoomScale :)。 – 2014-02-11 00:01:31

要做到这一点,最简单的方法就是将图片放入UIWebView(编写少量html包装代码,引用图片,而且基本完成)。更复杂的方法是使用touchesBegan,touchesMovedtouchesEnded跟踪用户的手指,并适当调整视图的transform属性。

+0

你可以建议我任何与你的答案有关的例子。如何使用touchesBegan,touchesMoved方法缩放和旋转图像。我的问题链接=> http://stackoverflow.com/questions/36833841/how-to-handle-multiple-touch-gesture-at-a-time?noredirect=1#comment61239098_36833841 – 2016-04-25 10:03:40

请记住,您永远不会放大UIImage。 EVER。

取而代之的是,您正在放大和缩小显示UIImageview

在这种特殊情况下,你chould选择创建一个自定义UIView与自定义绘图显示图像,一个UIImageView其显示图像的你,或UIWebView这将需要一些额外的HTML进行备份。

在任何情况下,您都需要执行touchesBegan,touchesMoved等来确定用户正在尝试做什么(缩放,平移等)。

+0

+1澄清,从未想过它这样,干杯伙计 – Elmo 2011-11-07 16:53:27

+0

@八月,你能给我提供什么样的缩放和旋转touchesBegan,touchesMoved图像的例子吗? – 2016-04-25 09:56:35

这是我以前用过的解决方案,不需要你使用UIWebView。

- (UIImage *)scaleAndRotateImage(UIImage *)image 
{ 
    int kMaxResolution = 320; // Or whatever 

    CGImageRef imgRef = image.CGImage; 

    CGFloat width = CGImageGetWidth(imgRef); 
    CGFloat height = CGImageGetHeight(imgRef); 


    CGAffineTransform transform = CGAffineTransformIdentity; 
    CGRect bounds = CGRectMake(0, 0, width, height); 
    if (width > kMaxResolution || height > kMaxResolution) { 
     CGFloat ratio = width/height; 
     if (ratio > 1) { 
      bounds.size.width = kMaxResolution; 
      bounds.size.height = bounds.size.width/ratio; 
     } 
     else { 
      bounds.size.height = kMaxResolution; 
      bounds.size.width = bounds.size.height * ratio; 
     } 
    } 

    CGFloat scaleRatio = bounds.size.width/width; 
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 
    CGFloat boundHeight; 
    UIImageOrientation orient = image.imageOrientation; 
    switch(orient) { 

     case UIImageOrientationUp: //EXIF = 1 
      transform = CGAffineTransformIdentity; 
      break; 

     case UIImageOrientationUpMirrored: //EXIF = 2 
      transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
      break; 

     case UIImageOrientationDown: //EXIF = 3 
      transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 
      transform = CGAffineTransformRotate(transform, M_PI); 
      break; 

     case UIImageOrientationDownMirrored: //EXIF = 4 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); 
      transform = CGAffineTransformScale(transform, 1.0, -1.0); 
      break; 

     case UIImageOrientationLeftMirrored: //EXIF = 5 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
      transform = CGAffineTransformRotate(transform, 3.0 * M_PI/2.0); 
      break; 

     case UIImageOrientationLeft: //EXIF = 6 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.width); 
      transform = CGAffineTransformRotate(transform, 3.0 * M_PI/2.0); 
      break; 

     case UIImageOrientationRightMirrored: //EXIF = 7 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeScale(-1.0, 1.0); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0); 
      break; 

     case UIImageOrientationRight: //EXIF = 8 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0); 
      break; 

     default: 
      [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 

    } 

    UIGraphicsBeginImageContext(bounds.size); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 
     CGContextScaleCTM(context, -scaleRatio, scaleRatio); 
     CGContextTranslateCTM(context, -height, 0); 
    } 
    else { 
     CGContextScaleCTM(context, scaleRatio, -scaleRatio); 
     CGContextTranslateCTM(context, 0, -height); 
    } 

    CGContextConcatCTM(context, transform); 

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef); 
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return imageCopy; 
} 

文章可以在Apple支持找到: http://discussions.apple.com/message.jspa?messageID=7276709#7276709

+0

-1为jsp托管的支持页面。 *在点语法中握拳* – esharp 2014-11-18 05:46:14

+0

您能否告诉我如何调用此方法(在鼠标移动或触摸上)? – 2017-04-17 13:07:41

下面的代码有助于放大的UIImageView不使用的UIScrollView:

-(void)HandlePinch:(UIPinchGestureRecognizer*)recognizer{ 
    if ([recognizer state] == UIGestureRecognizerStateEnded) { 
     NSLog(@"======== Scale Applied ==========="); 
     if ([recognizer scale]<1.0f) { 
      [recognizer setScale:1.0f]; 
     } 
     CGAffineTransform transform = CGAffineTransformMakeScale([recognizer scale], [recognizer scale]); 
     imgView.transform = transform; 
    } 
} 
+0

这是至高无上的解决方案:)。谢谢。 – sabiland 2017-06-24 05:52:18

Shefali对UIImageView的解决方案的伟大工程,但它需要一点修改:

- (void)pinch:(UIPinchGestureRecognizer *)gesture { 
    if (gesture.state == UIGestureRecognizerStateEnded 
     || gesture.state == UIGestureRecognizerStateChanged) { 
     NSLog(@"gesture.scale = %f", gesture.scale); 

     CGFloat currentScale = self.frame.size.width/self.bounds.size.width; 
     CGFloat newScale = currentScale * gesture.scale; 

     if (newScale < MINIMUM_SCALE) { 
      newScale = MINIMUM_SCALE; 
     } 
     if (newScale > MAXIMUM_SCALE) { 
      newScale = MAXIMUM_SCALE; 
     } 

     CGAffineTransform transform = CGAffineTransformMakeScale(newScale, newScale); 
     self.transform = transform; 
     gesture.scale = 1; 
    } 
} 

(Shefali的解决方案有缺点,它挤压时不连续缩放。此外,当开始一个新的捏,当前的图像缩放被重置。)

+0

我想在捏手势开始后启用平移手势启用。怎么做? – 2012-06-28 09:16:28

正如其他人所述,最简单的解决方案是将您的UIImageView放入UIScrollView。我在Interface Builder .xib文件中做了这个。

在viewDidLoad中,设置以下变量。将您的控制器设置为UIScrollViewDelegate。

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.scrollView.minimumZoomScale = 0.5; 
    self.scrollView.maximumZoomScale = 6.0; 
    self.scrollView.contentSize = self.imageView.frame.size; 
    self.scrollView.delegate = self; 
} 

您需要实现以下方法才能返回要放大的imageView。

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 
{ 
    return self.imageView; 
} 

在之前的版本iOS9,你可能还需要添加这个空的委托方法:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale 
{ 
} 

Apple Documentation确实描述了如何做到这一点的一个好工作:

Shafali和JRV的答案扩展到包括平移和捏缩放:

#define MINIMUM_SCALE 0.5 
#define MAXIMUM_SCALE 6.0 
@property CGPoint translation; 


- (void)pan:(UIPanGestureRecognizer *)gesture { 
    static CGPoint currentTranslation; 
    static CGFloat currentScale = 0; 
    if (gesture.state == UIGestureRecognizerStateBegan) { 
     currentTranslation = _translation; 
     currentScale = self.view.frame.size.width/self.view.bounds.size.width; 
    } 
    if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) { 

     CGPoint translation = [gesture translationInView:self.view]; 

     _translation.x = translation.x + currentTranslation.x; 
     _translation.y = translation.y + currentTranslation.y; 
     CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x , _translation.y); 
     CGAffineTransform transform2 = CGAffineTransformMakeScale(currentScale, currentScale); 
     CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2); 
     self.view.transform = transform; 
    } 
} 


- (void)pinch:(UIPinchGestureRecognizer *)gesture { 
    if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) { 
//  NSLog(@"gesture.scale = %f", gesture.scale); 

     CGFloat currentScale = self.view.frame.size.width/self.view.bounds.size.width; 
     CGFloat newScale = currentScale * gesture.scale; 

     if (newScale < MINIMUM_SCALE) { 
      newScale = MINIMUM_SCALE; 
     } 
     if (newScale > MAXIMUM_SCALE) { 
      newScale = MAXIMUM_SCALE; 
     } 

     CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x, _translation.y); 
     CGAffineTransform transform2 = CGAffineTransformMakeScale(newScale, newScale); 
     CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2); 
     self.view.transform = transform; 
     gesture.scale = 1; 
    } 
} 

保留记住你不想放大/缩小UIImage。请尝试放大或缩小包含UIImage View Controller的View。

我已经为这个问题做了一个解决方案。看看我的代码:

@IBAction func scaleImage(sender: UIPinchGestureRecognizer) { 
     self.view.transform = CGAffineTransformScale(self.view.transform, sender.scale, sender.scale) 
     sender.scale = 1 
    } 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
     view.backgroundColor = UIColor.blackColor() 
    } 

N.B .:不要忘记连接PinchGestureRecognizer。