사용자가 화면을 집을 때 UIImage 객체를 확대 / 축소하는 방법은 무엇입니까?


84

사용자가 내 응용 프로그램에서 표준 핀치 작업을 수행 할 때 UIImage 개체를 확대 / 축소하고 싶습니다. 해당 세부 사항이 어떤 식 으로든 도움이된다면 현재 UIImageView를 사용하여 이미지를 표시하고 있습니다.

나는 이것을하는 방법을 알아 내려고 노력하고 있지만 지금까지 그러한 운이 없습니다.

단서가 있습니까?

답변:


85

이를 수행하는 또 다른 쉬운 방법 UIImageViewUIScrollView. 여기 에서 설명했듯이 스크롤 뷰의 contentSize를 UIImageView's크기 와 동일하게 설정해야 합니다. 컨트롤러 인스턴스를 스크롤 뷰의 델리게이트로 설정하고 핀치 확대 및 이미지 패닝을 허용 하는 viewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale:메서드를 구현합니다 . 이것은 전체 웹보기의 오버 헤드가 없기 때문에 Ben의 솔루션이 약간 더 가벼운 방식으로 수행하는 작업입니다.

발생할 수있는 한 가지 문제는 스크롤 뷰 내의 크기 조정이 이미지에 적용된 변환 형식으로 제공된다는 것입니다. 이는 높은 줌 배율에서 흐릿함을 유발할 수 있습니다. 다시 그릴 수있는 항목의 경우 핀치 제스처가 완료된 후 더 선명한 디스플레이를 제공하기 위해 여기 에서 제 제안을 따를 수 있습니다 . 그 시점에서 hniels의 솔루션을 사용하여 이미지의 크기를 조정할 수 있습니다.


2
maximumZoomScale 및 / 또는 minimumZoomScale :)을 변경했는지 확인하십시오.
Chris Prince

94

다른 사람들이 설명했듯이 가장 쉬운 해결책은 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
{
}

애플 문서는 이 작업을 수행하는 방법을 설명하는 좋은 일을한다 :


3
scrollViewDidEndZooming : withView를 삭제해도 괜찮습니다 : 이제 iOS9 Xcode7
ElonChan으로

1
그것은 나를 위해 작동합니다! 구현 scrollViewDidEndZooming :방법 없이 .
Johnny Zhang

48

UIImageView에 대한 Shefali의 솔루션은 훌륭하게 작동하지만 약간의 수정이 필요합니다.

- (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의 솔루션은 꼬집는 동안 연속적으로 확장되지 않는다는 단점이 있습니다. 또한 새 핀치를 시작할 때 현재 이미지 배율이 재설정되었습니다.)


핀치 제스처가 시작된 후 팬 제스처를 활성화하려면 어떻게해야합니까?
Gajendra K Chauhan 2012-06-28

@Gajendra :이 경우에는 두 가지 모두를 지원하는 스크롤보기에 구성 요소를 포함해야한다고 생각합니다.
JRV

하지만 탭 제스처와 핀치 제스처 모두에 대한 기능을 원합니다. Imageview에서 그리드 (레이어)도 사용했습니다. 스크롤보기에서 핀치 제스처 및 탭 제스처를 사용할 수 있는지 알고 싶습니다.
Gajendra K Chauhan 2012-06-29

@GajendraKChauhan : 스크롤보기는 핀치로 확대 / 축소 및 상자 밖으로 이동을 지원합니다. 최소 / 최대 확대 / 축소 배율을 설정하는 것을 잊지 말고 Brad Larsons 답변도 살펴보세요. 탭 제스처도 원한다면 제스처로 추가 할 수 있습니다.
JRV

@JRV, self.frame.size.width를 인식하려면 어떤 델리게이트를 추가해야합니까?

23

아래 코드는 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;
    }
}

이것은 최고의 솔루션입니다 :). 고마워.
sabiland

19

절대로 UIImage. 이제까지.

대신에의 확대 및 축소하고 view그 표시합니다 UIImage.

이 특정한 경우에, 당신은 사용자 정의 만들 수 chould UIViewA, 이미지를 표시하는 사용자 정의 그리기를 UIImageView당신을 위해 이미지를 표시하는, 또는 UIWebView몇 가지 추가적인 HTML을해야 할 것이다 그것을 백업 할 수 있습니다.

모든 경우에, 당신은 구현해야합니다 touchesBegan, touchesMoved그리고 같은 사용자가 (줌, 팬 등)을 수행하려고 결정 할 수 있습니다.


+1 설명을 위해 그런 식으로 생각한 적이 없습니다. 환호합니다
Elmo

@August, touchesBegan, touchesMoved에서 이미지를 확대 / 축소하고 회전하는 예제를 제공 할 수 있습니까?
Mitesh Dobareeya

7

다음은 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) 에서 찾을 수 있습니다.


jsp 호스팅 지원 페이지의 경우 -1입니다. 쉐이크는 도트 구문에서 주먹
esharp

이 메서드를 호출하는 방법을 알려주시겠습니까 (마우스 이동 또는 터치시)?
Bhumesh Purohit

5

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

다른 사람의 답변은 언제든지 삭제할 수 있으므로 언급하지 마시기 바랍니다.
Enamul Hassan 2015

3

이 작업을 수행하는 가장 간단한 방법은 핀치 확대 / 축소 만 있으면 이미지를 내부에 배치하는 것입니다 UIWebView(적은 양의 html 래퍼 코드를 작성하고 이미지를 참조하면 기본적으로 완료됩니다). 이 작업을 수행하는 더 complcated 방법은 사용하는 것입니다 touchesBegan, touchesMoved그리고 touchesEnded사용자의 손가락을 추적하고보기의 적절 transform 속성을 조정합니다.


귀하의 답변과 관련된 예를 제안 해 주시겠습니까? touchesBegan, touchesMoved 메서드를 사용하여 이미지를 확대 / 축소하고 회전하려면 어떻게해야합니까? 내 질문 링크 => stackoverflow.com/questions/36833841/…
Mitesh Dobareeya

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

주의 : PinchGestureRecognizer를 연결하는 것을 잊지 마십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.