ユーザーが画面をつまんだときにUIImageオブジェクトをズームイン/ズームアウトするにはどうすればよいですか?


84

ユーザーがアプリケーションで標準のピンチアクションを実行したときに、UIImageオブジェクトをズームイン/ズームアウトしたいと思います。私は現在、UIImageViewを使用して画像を表示していますが、その詳細が何らかの形で役立つ場合は。

私はこれを行う方法を理解しようとしていますが、今のところそのような運はありません。

手がかりはありますか?

回答:


85

これを行うもう1つの簡単な方法は、UIImageView内にを配置することUIScrollViewです。 ここ説明するように、スクロールビューのcontentSizeをUIImageView'sサイズと同じに設定する必要があります。コントローラインスタンスをスクロールビューのデリゲートとして設定し、ピンチズームと画像パンを可能にするメソッドviewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale:メソッドを実装します。これは事実上、Benのソリューションが行うことですが、完全なWebビューのオーバーヘッドがないため、わずかに軽量化されています。

発生する可能性のある問題の1つは、スクロールビュー内のスケーリングが、画像に適用される変換の形式で行われることです。これにより、ズーム率が高いとぼやける可能性があります。再描画できるものについては、ここでの私の提案に従って、ピンチジェスチャが終了した後に鮮明な表示を提供できます。その時点で、hnielsのソリューションを使用して画像を再スケーリングできます。


2
maximumZoomScaleおよび/またはminimumZoomScaleを変更してください:)。
クリスプリンス

94

他の人が説明したように、最も簡単な解決策はUIImageViewをUIScrollViewに配置することです。私はこれをInterfaceBuilderの.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 :メソッドを実装せずに。
ジョニーチャン

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年

@Gajendra:その場合、コンポーネントをスクロールビューに埋め込む必要があると思います。これは、箱から出して両方をサポートします
JRV 2012年

しかし、タップジェスチャとピンチジェスチャの両方の機能が必要です。Imageviewでもグリッド(レイヤー)を使用しています。スクロールビューでピンチジェスチャとタップジェスチャを使用することはできますか?
Gajendra K Chauhan 2012年

@GajendraKChauhan:スクロールビューは、ピンチによるズームとボックスからのパンをサポートしています。最小/最大ズームスケールを設定することを忘れないでください。ただし、BradLarsonsの回答も参照してください。また、タップジェスチャも必要な場合は、それをジェスチャとして追加できます。
JRV 2012年

@ 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 2017年

19

にズームインすることは決してないことに注意してくださいUIImage。これまで。

代わりに、viewを表示するにズームインおよびズームアウトしていますUIImage

この特定のケースではUIView、画像を表示するカスタム図面を使用してカスタムを作成するか、画像を表示するUIImageViewか、またはUIWebViewバックアップするために追加のHTMLが必要になるかを選択する必要があります。

すべてのケースでは、実装する必要がありますtouchesBegantouchesMovedユーザーは(ズーム、パンなど)をやろうとしているかを決定するために、などが挙げられます。


明確にするために+1、そのように考えたことはありません、男を応援します
エルモ

@ August、touchesBegan、touchesMovedで画像をズームおよび回転する例を教えてください。
Mitesh Dobareeya 2016

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 2014年

このメソッドの呼び出し方法(マウスの移動またはタッチ)を教えてください。
Bhumesh Purohit 2017

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方法が使用することですtouchesBegantouchesMovedtouchesEndedユーザの指を追跡し、あなたのビューのが適切transformプロパティを調整します。


あなたの答えに関連する例を教えてもらえますか?touchesBegan、touchesMovedメソッドを使用して画像をズームおよび回転するにはどうすればよいですか。私の質問のリンク=> stackoverflow.com/questions/36833841/...
Mitesh Dobareeya

0

UIImageをズームイン/ズームアウトしたくないことに注意してください。代わりに、UIImage ViewControllerを含むビューをズームイン/ズームアウトしてみてください。

私はこの問題の解決策を作りました。私のコードを見てください:

@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.