如何在用户捏屏幕时放大/缩小UIImage对象?
我想放大/缩小一个UIImage对象,当用户在我的应用程序执行标准的捏动作。 我正在使用UIImageView来显示我的图像,如果这些细节有任何帮助。
我试图找出如何做到这一点,但迄今没有这样的运气。
任何线索?
另一个简单的方法是将你的UIImageView
放在一个UIScrollView
。 正如我在这里所描述的 ,你需要将滚动视图的contentSize设置为和你的UIImageView's
大小相同。 将您的控制器实例设置为滚动视图的委托,并实现viewForZoomingInScrollView:
和scrollViewDidEndZooming:withView:atScale:
方法以允许捏缩放和图像平移。 这实际上是Ben的解决scheme所做的,只是以一种轻量级的方式,因为你没有一个完整的Web视图的开销。
你可能碰到的一个问题是,滚动视图中的缩放比例是以应用于图像的变换的forms出现的。 这可能导致高变焦因素模糊。 对于可以重新绘制的东西,可以按照我的build议在捏合手势完成后提供更清晰的显示。 hniels的解决scheme可以用来在这一点上重新调整你的形象。
正如其他人所描述的,最简单的解决scheme是把你的UIImageView放入一个UIScrollView。 我在Interface Builder .xib文件中做了这个。
在viewDidLoad中,设置下列variables。 设置你的控制器是一个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 { }
苹果文档在描述如何做到这一点上做得很好:
Shefali的UIImageView解决scheme效果很好,但需要稍微修改一下:
- (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的解决scheme有一个缺点,即它不会在缩放的同时连续缩放,而且,当启动一个新的缩放时,当前的图像缩放被重置)。
下面的代码有助于在不使用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; } }
请记住,你从来没有放大在UIImage
。 EVER。
相反,您正在放大和缩小显示UIImage
的view
。
在这种情况下,你应该select创build一个自定义的UIView
来显示图像,一个UIImageView
为你显示图像,或者一个UIWebView
,它需要一些额外的HTML来备份它。
在所有情况下,您都需要实现touchesBegan
, touchesMoved
等来确定用户正在尝试做什么(缩放,平移等)。
这是我之前使用过的一个解决scheme,不需要你使用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; }
该文章可以在苹果支持网站上find: http : //discussions.apple.com/message.jspa?messageID=7276709#7276709
沙法利和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; } }
要做到这一点,最简单的方法就是把图像放在一个UIWebView
(写less量的html包装代码,引用你的图像,而且基本上完成了)。 更复杂的方法是使用touchesBegan
, touchesMoved
和touchesEnded
来跟踪用户的手指,并适当调整视图的transform属性。
请记住,你不想放大/缩小UIImage。 而是尝试放大/缩小包含UIImage视图控制器的视图。
我已经为这个问题做了一个解决scheme。 看看我的代码:
@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。