当用户在我的应用程序上执行标准捏合操作时,我想放大/缩小 UIImage 对象。我目前正在使用 UIImageView 来显示我的图像,如果该细节有任何帮助的话。
我试图弄清楚如何做到这一点,但到目前为止还没有这样的运气。
有什么线索吗?
当用户在我的应用程序上执行标准捏合操作时,我想放大/缩小 UIImage 对象。我目前正在使用 UIImageView 来显示我的图像,如果该细节有任何帮助的话。
我试图弄清楚如何做到这一点,但到目前为止还没有这样的运气。
有什么线索吗?
正如其他人所描述的,最简单的解决方案是将您的 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 文档很好地描述了如何执行此操作:
另一种简单的方法是把你UIImageView
放在一个UIScrollView
. 正如我在这里所描述的,您需要将滚动视图的 contentSize 设置为与您的UIImageView's
大小相同。将您的控制器实例设置为滚动视图的委托,并实现viewForZoomingInScrollView:
和scrollViewDidEndZooming:withView:atScale:
方法以允许缩放和图像平移。这实际上是 Ben 的解决方案所做的,只是以更轻量级的方式,因为您没有完整 Web 视图的开销。
您可能会遇到的一个问题是滚动视图中的缩放以应用于图像的变换的形式出现。这可能导致在高缩放因子下的模糊。对于可以重绘的内容,您可以在此处按照我的建议在捏合手势完成后提供更清晰的显示。那时可以使用 hniels 的解决方案来重新缩放您的图像。
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 的解决方案的缺点是在捏合时不会连续缩放。此外,当开始新的捏合时,当前的图像比例会被重置。)
下面的代码有助于在不使用 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
. 曾经。
相反,您正在放大和缩小view
显示UIImage
.
在这种特殊情况下,您可以选择UIView
使用自定义绘图创建一个自定义来显示图像,一个UIImageView
为您显示图像,或者一个UIWebView
需要一些额外的 HTML 来备份它。
在所有情况下,您都需要实现touchesBegan
、touchesMoved
等来确定用户正在尝试做什么(缩放、平移等)。
这是我之前使用过的解决方案,不需要您使用 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
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;
}
}
最简单的方法,如果你想要的只是捏缩放,就是把你的图像放在一个UIWebView
(编写少量的 html 包装器代码,引用你的图像,你基本上就完成了)。更复杂的方法是使用touchesBegan
、touchesMoved
和touchesEnded
来跟踪用户的手指,并适当地调整视图的变换属性。
请记住,您不想放大/缩小 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。