2009-02-01 137 views
71

我想放大/縮小UIImage對象,當用戶在我的應用程序上執行標準捏合動作。我正在使用UIImageView來顯示我的圖像,如果這些細節有任何幫助。如何在用戶捏屏幕時放大/縮小UIImage對象?

我想弄清楚如何做到這一點,但迄今沒有這樣的運氣。

任何線索?

回答

77

另一種簡單的方法來做到這一點是把你的UIImageViewUIScrollViewAs I describe here,您需要將滾動視圖的contentSize設置爲與您的UIImageView's大小相同。將您的控制器實例設置爲滾動視圖的代表,並實施viewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale:方法以允許捏縮放和圖像平移。這實際上就是Ben的解決方案所做的事情,只是以輕量級的方式,因爲您沒有完整的Web視圖的開銷。

您可能遇到的一個問題是滾動視圖中的縮放比例是以應用於圖像的轉換形式出現的。這可能導致高變焦係數模糊。對於可以重繪的內容,您可以按照我的建議here在捏合手勢完成後提供更清晰的顯示。 hniels的解決方案可以用來重新調整圖像。

+2

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

2

要做到這一點,最簡單的方法就是將圖片放入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

18

請記住,您永遠不會放大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

8

這是我以前用過的解決方案,不需要你使用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

22

下面的代碼有助於放大的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

48

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

75

正如其他人所述,最簡單的解決方案是將您的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確實描述瞭如何做到這一點的一個好工作:

4

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

保留記住你不想放大/縮小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。

相關問題