【问题标题】:How to zoom in/out an UIImage object when user pinches screen?用户捏屏幕时如何放大/缩小 UIImage 对象?
【发布时间】:2010-10-04 17:49:06
【问题描述】:

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

我正在尝试弄清楚如何做到这一点,但到目前为止还没有这样的运气。

有什么线索吗?

【问题讨论】:

    标签: cocoa-touch uiimage uiimagejpegrepresentation


    【解决方案1】:

    正如其他人所描述的,最简单的解决方案是将您的 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 很好地描述了如何执行此操作:

    【讨论】:

    • 现在可以删除scrollViewDidEndZooming:withView: 用iOS9 Xcode7测试过
    • 它对我有用!没有实现scrollViewDidEndZooming : 方法。
    【解决方案2】:

    请记住,您不想放大/缩小 UIImage。而是尝试放大/缩小包含 UIImage 视图控制器的视图。

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

    @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()
        }
    

    注意:不要忘记连接 PinchGestureRecognizer。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 请避免提及其他人的答案,因为他们可以随时删除他们的答案。
      【解决方案4】:

      这是我之前使用过的解决方案,不需要您使用 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

      【讨论】:

      • -1 用于 jsp 托管支持页面。 对点语法握拳
      • 你能告诉我如何调用这个方法(鼠标移动或触摸)吗?
      【解决方案5】:

      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 的解决方案的缺点是在捏合时不会连续缩放。此外,当开始新的捏合时,当前的图像比例会被重置。)

      【讨论】:

      • 我想在捏合手势开始后启用平移手势。怎么做?
      • @Gajendra:在这种情况下,我认为你应该使用将组件嵌入到滚动视图中,它支持开箱即用
      • 但我想要轻点手势和捏合手势的功能。我还在 Imageview 上使用了网格(图层)。请问,是否可以在滚动视图中使用捏合手势和点击手势?
      • @GajendraKChauhan:滚动视图支持缩放和平移开箱即用 - 只需记住设置最小/最大缩放比例,但还要看看 Brad Larsons 的回答。如果您还想要点击手势,您可以将其添加为手势。
      • @JRV,我需要添加哪些代表才能让 self.frame.size.width 被识别?
      【解决方案6】:

      以下代码有助于在不使用 UIScrollView 的情况下缩放 UIImageView :

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

      【讨论】:

      • 这是最佳解决方案:)。谢谢。
      【解决方案7】:

      另一种简单的方法是将UIImageView 放在UIScrollView 中。 As I describe here,您需要将滚动视图的 contentSize 设置为与您的 UIImageView's 大小相同。将您的控制器实例设置为滚动视图的委托,并实现viewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale: 方法以允许缩放和图像平移。这实际上是 Ben 的解决方案所做的,只是以更轻量级的方式,因为您没有完整 Web 视图的开销。

      您可能遇到的一个问题是滚动视图中的缩放以应用于图像的变换的形式出现。这可能导致在高缩放因子下的模糊。对于可以重绘的东西,您可以按照我的建议here 在捏合手势完成后提供更清晰的显示。那时可以使用 hniels 的解决方案来重新缩放您的图像。

      【讨论】:

      • 确保更改 maximumZoomScale 和/或 minimumZoomScale :)。
      【解决方案8】:

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

      相反,您正在放大和缩小显示UIImageview

      在这种特殊情况下,您可以选择使用自定义绘图创建自定义 UIView 以显示图像,UIImageView 为您显示图像,或者 UIWebView 需要一些额外的 HTML 来支持起来吧。

      在所有情况下,您都需要实现touchesBegantouchesMoved 等来确定用户尝试执行的操作(缩放、平移等)。

      【讨论】:

      • +1 澄清一下,从来没有这么想过,干杯老兄
      • @August,你能给我提供在 touchesBegan、touchesMoved 上缩放和旋转图像的任何例子吗?
      【解决方案9】:

      最简单的方法,如果你想要的只是捏缩放,是把你的图像放在UIWebView 中(编写少量的 html 包装代码,引用你的图像,你基本上就完成了)。更复杂的方法是使用touchesBegantouchesMovedtouchesEnded 来跟踪用户的手指,并适当调整视图的变换属性。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 2012-11-23
      • 1970-01-01
      • 2021-01-24
      • 2016-07-16
      • 2020-05-09
      • 2011-09-18
      相关资源
      最近更新 更多