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

发布于 2024-07-12 05:40:07 字数 150 浏览 4 评论 0原文

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

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

有什么线索吗?

I would like to zoom in/out an UIImage object when the user performs the standard pinch action on my application. I'm currently using a UIImageView to display my image, if that detail helps in any way.

I'm trying to figure out how to do this, but no such luck so far.

Any clues?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

虐人心 2024-07-19 05:40:07

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

As others described, the easiest solution is to put your UIImageView into a UIScrollView. I did this in the Interface Builder .xib file.

In viewDidLoad, set the following variables. Set your controller to be a 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;
}

You are required to implement the following method to return the imageView you want to zoom.

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

In versions prior to iOS9, you may also need to add this empty delegate method:

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

The Apple Documentation does a good job of describing how to do this:

不必了 2024-07-19 05:40:07

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

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

Another easy way to do this is to place your UIImageView within a UIScrollView. As I describe here, you need to set the scroll view's contentSize to be the same as your UIImageView's size. Set your controller instance to be the delegate of the scroll view and implement the viewForZoomingInScrollView: and scrollViewDidEndZooming:withView:atScale: methods to allow for pinch-zooming and image panning. This is effectively what Ben's solution does, only in a slightly more lightweight manner, as you don't have the overhead of a full web view.

One issue you may run into is that the scaling within the scroll view comes in the form of transforms applied to the image. This may lead to blurriness at high zoom factors. For something that can be redrawn, you can follow my suggestions here to provide a crisper display after the pinch gesture is finished. hniels' solution could be used at that point to rescale your image.

空宴 2024-07-19 05:40:07

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

Shefali's solution for UIImageView works great, but it needs a little modification:

- (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's solution had the downside that it did not scale continuously while pinching. Furthermore, when starting a new pinch, the current image scale was reset.)

倾城花音 2024-07-19 05:40:07

下面的代码有助于在不使用 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;
    }
}

Below code helps to zoom UIImageView without using 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;
    }
}
浸婚纱 2024-07-19 05:40:07

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

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

在这种特殊情况下,您可以选择创建一个带有自定义绘图的自定义 UIView 来显示图像、一个为您显示图像的 UIImageView 或一个 UIWebView 这将需要一些额外的 HTML 来支持它。

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

Keep in mind that you're NEVER zooming in on a UIImage. EVER.

Instead, you're zooming in and out on the view that displays the UIImage.

In this particular case, you chould choose to create a custom UIView with custom drawing to display the image, a UIImageView which displays the image for you, or a UIWebView which will need some additional HTML to back it up.

In all cases, you'll need to implement touchesBegan, touchesMoved, and the like to determine what the user is trying to do (zoom, pan, etc.).

水溶 2024-07-19 05:40:07

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

Here is a solution I've used before that does not require you to use the 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;
}

The article can be found on Apple Support at:
http://discussions.apple.com/message.jspa?messageID=7276709#7276709

芸娘子的小脾气 2024-07-19 05:40:07

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

Shafali and JRV's answers extended to include panning and pinch to zoom:

#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 包装器代码,引用您的图像,基本上就完成了) 。 更复杂的方法是使用 touchesBegantouchesMovedtouchesEnded 来跟踪用户的手指,并调整视图的变换财产适当。

The simplest way to do this, if all you want is pinch zooming, is to place your image inside a UIWebView (write small amount of html wrapper code, reference your image, and you're basically done). The more complcated way to do this is to use touchesBegan, touchesMoved, and touchesEnded to keep track of the user's fingers, and adjust your view's transform property appropriately.

夏末染殇 2024-07-19 05:40:07

请记住,您不想放大/缩小 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。

Keep in mind that you don't want to zoom in/out UIImage. Instead try to zoom in/out the View which contains the UIImage View Controller.

I have made a solution for this problem. Take a look at my code:

@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.: Don't forget to hook up the PinchGestureRecognizer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文