Làm cách nào để phóng to / thu nhỏ một đối tượng Hình ảnh toàn cảnh khi người dùng chụm màn hình?


84

Tôi muốn phóng to / thu nhỏ đối tượng UIImage khi người dùng thực hiện hành động chụm tiêu chuẩn trên ứng dụng của tôi. Tôi hiện đang sử dụng UIImageView để hiển thị hình ảnh của mình, nếu chi tiết đó hữu ích theo bất kỳ cách nào.

Tôi đang cố gắng tìm cách làm điều này, nhưng không có may mắn cho đến nay.

Bất kì manh mối nào?

Câu trả lời:


85

Một cách dễ dàng khác để làm điều này là đặt của bạn UIImageViewtrong một UIScrollView. Như tôi mô tả ở đây , bạn cần đặt contentSize của chế độ xem cuộn bằng với UIImageView'skích thước của bạn . Đặt phiên bản bộ điều khiển của bạn làm đại biểu của chế độ xem cuộn và triển khai các phương thức viewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale:để cho phép chụm-phóng to và xoay hình ảnh. Đây là hiệu quả mà giải pháp của Ben thực hiện, chỉ ở mức độ nhẹ hơn một chút, vì bạn không có chi phí để xem toàn bộ trang web.

Một vấn đề bạn có thể gặp phải là tỷ lệ trong chế độ xem cuộn có dạng biến đổi được áp dụng cho hình ảnh. Điều này có thể dẫn đến mờ ở các hệ số thu phóng cao. Đối với nội dung nào đó có thể được vẽ lại, bạn có thể làm theo các đề xuất của tôi tại đây để cung cấp màn hình sắc nét hơn sau khi kết thúc cử chỉ chụm. giải pháp hniels 'có thể được sử dụng tại thời điểm đó để bán lại hình ảnh của bạn.


2
Đảm bảo bạn thay đổi tối đaZoomScale và / hoặc tối thiểuZoomScale :).
Chris Prince

94

Như những người khác đã mô tả, giải pháp đơn giản nhất là đặt UIImageView của bạn vào UIScrollView. Tôi đã làm điều này trong tệp .xib của Trình tạo giao diện.

Trong viewDidLoad, hãy đặt các biến sau. Đặt bộ điều khiển của bạn thành 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;
}

Bạn bắt buộc phải triển khai phương pháp sau để trả về imageView mà bạn muốn thu phóng.

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

Trong các phiên bản trước iOS9, bạn cũng có thể cần thêm phương thức đại biểu trống này:

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

Các tài liệu của Apple làm một công việc tốt của mô tả làm thế nào để làm điều này:


3
Có thể xóa scrollViewDidEndZooming: withView: bây giờ, tôi đã thử nghiệm với iOS9 Xcode7
ElonChan

1
Nó hoạt động cho tôi! Nếu không có scrollViewDidEndZooming :phương pháp thực hiện .
Johnny Zhang

48

Giải pháp của Shefali cho UIImageView hoạt động tuyệt vời, nhưng nó cần sửa đổi một chút:

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

(Giải pháp của Shefali có nhược điểm là nó không chia tỷ lệ liên tục trong khi chụm. Hơn nữa, khi bắt đầu chụm mới, tỷ lệ hình ảnh hiện tại được đặt lại.)


Tôi muốn bật cử chỉ xoay sau khi cử chỉ chụm bắt đầu. Làm thế nào để làm điều đó?
Gajendra K Chauhan

@Gajendra: Trong trường hợp đó, tôi nghĩ bạn nên sử dụng tính năng nhúng các thành phần của mình vào chế độ xem cuộn, hỗ trợ cả hai tính năng này
JRV

Nhưng tôi muốn có chức năng cho cả cử chỉ chạm và cử chỉ chụm. Tôi cũng đã sử dụng lưới (các lớp) trên Imageview. Tôi có thể biết, Có thể sử dụng cử chỉ chụm và chạm trong chế độ xem cuộn không.?
Gajendra K Chauhan

@GajendraKChauhan: Chế độ xem cuộn hỗ trợ chụm để thu phóng và xoay ra khỏi hộp - chỉ cần nhớ đặt tỷ lệ thu phóng tối thiểu / tối đa, nhưng cũng hãy xem câu trả lời của Brad Larsons. Và nếu bạn muốn cả cử chỉ chạm, bạn có thể thêm cử chỉ đó làm cử chỉ.
JRV

@JRV, tôi cần thêm đại biểu nào để nhận diện self.frame.size.width?

23

Đoạn mã dưới đây giúp thu phóng UIImageView mà không cần sử dụng 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;
    }
}

Đây là giải pháp tối cao :). Cám ơn.
sabiland

19

Hãy nhớ rằng bạn KHÔNG BAO GIỜ phóng to trên a UIImage. KHÔNG BAO GIỜ.

Thay vào đó, bạn đang phóng to và thu nhỏ viewmàn hình hiển thị UIImage.

Trong trường hợp cụ thể này, bạn nên chọn tạo tùy chỉnh UIViewvới bản vẽ tùy chỉnh để hiển thị hình ảnh, tùy chọn UIImageViewhiển thị hình ảnh cho bạn hoặc UIWebViewsẽ cần một số HTML bổ sung để sao lưu.

Trong mọi trường hợp, bạn sẽ cần phải thực hiện touchesBegan, touchesMovedvà những thứ tương tự để xác định những gì người dùng đang cố gắng làm (zoom, pan, vv).


+1 để làm rõ, không bao giờ nghĩ về nó theo cách đó, cổ vũ anh bạn
Elmo

@August, bạn có thể cung cấp cho tôi bất kỳ ví dụ nào về cách thu phóng và xoay hình ảnh trên touchBegan, touchMoved không?
Mitesh Dobareeya

7

Đây là một giải pháp tôi đã sử dụng trước đây mà không yêu cầu bạn sử dụng 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;
}

Bạn có thể tìm thấy bài viết trên Bộ phận hỗ trợ của Apple tại: http://discussions.apple.com/message.jspa?messageID=7276709#7276709


-1 cho một trang hỗ trợ được lưu trữ trên máy chủ jsp. lắc nắm tay theo cú pháp dấu chấm
esharp

Bạn có thể vui lòng cung cấp cho tôi cách gọi phương thức này (khi di chuyển chuột hoặc chạm) không?
Bhumesh Purohit

5

Câu trả lời của Shafali và JRV mở rộng để bao gồm lia và chụm để thu phóng:

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

vui lòng tránh đề cập đến câu trả lời của người khác vì họ có thể xóa câu trả lời của mình bất cứ lúc nào.
Enamul Hassan

3

Cách đơn giản nhất để làm điều này, nếu tất cả những gì bạn muốn là phóng to, là đặt hình ảnh của bạn bên trong một UIWebView(viết một lượng nhỏ mã trình bao bọc html, tham chiếu hình ảnh của bạn và về cơ bản bạn đã hoàn thành). Cách complcated hơn để làm điều này là sử dụng touchesBegan, touchesMovedtouchesEndedđể theo dõi các ngón tay của người dùng, và điều chỉnh quan điểm của bạn chuyển đổi bất động sản một cách thích hợp.


u có thể gợi ý cho tôi bất kỳ ví dụ nào liên quan đến câu trả lời của bạn. Làm cách nào để tôi có thể thu phóng và xoay hình ảnh bằng các phương pháp touchBegan, touchMoved. Liên kết câu hỏi của tôi => stackoverflow.com/questions/36833841/…
Mitesh Dobareeya,

0

Hãy nhớ rằng bạn không muốn phóng to / thu nhỏ Hình ảnh toàn cảnh. Thay vào đó, hãy cố gắng phóng to / thu nhỏ Chế độ xem có chứa Bộ điều khiển Chế độ xem Hình ảnh.

Tôi đã thực hiện một giải pháp cho vấn đề này. Hãy xem mã của tôi:

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

NB: Đừng quên kết nối PinchGestureRecognizer.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.