Kullanıcı ekranı sıkıştırdığında bir UIImage nesnesine nasıl yakınlaştırma / uzaklaştırma yapılır?


84

Kullanıcı, uygulamamda standart kıstırma eylemini gerçekleştirdiğinde bir UIImage nesnesini yakınlaştırmak / uzaklaştırmak istiyorum. Bu ayrıntı herhangi bir şekilde yardımcı olursa, şu anda resmimi görüntülemek için bir UIImageView kullanıyorum.

Bunu nasıl yapacağımı bulmaya çalışıyorum ama şimdiye kadar böyle bir şans yok.

Herhangi bir ipucu?

Yanıtlar:


85

Bunu yapmanın bir başka kolay yolu da UIImageViewbir UIScrollView. Burada anlattığım gibi , kaydırma görünümünün contentSize değerini bedeninizle aynı olacak şekilde ayarlamanız gerekir UIImageView's. Denetleyici örneğinizi kaydırma görünümünün temsilcisi olacak şekilde ayarlayın viewForZoomingInScrollView:ve scrollViewDidEndZooming:withView:atScale:sıkıştırarak yakınlaştırmaya ve görüntü kaydırmaya izin vermek için ve yöntemlerini uygulayın. Tam bir web görünümünün ek yüküne sahip olmadığınız için, Ben'in çözümünün etkili bir şekilde yaptığı şey budur, ancak biraz daha hafif bir şekilde.

Karşılaşabileceğiniz bir sorun, kaydırma görünümündeki ölçeklemenin görüntüye uygulanan dönüştürmeler biçiminde gelmesidir. Bu, yüksek yakınlaştırma faktörlerinde bulanıklığa neden olabilir. Yeniden çizilebilecek bir şey için , kıstırma hareketi bittikten sonra daha canlı bir görüntü sağlamak için önerilerimi buradan takip edebilirsiniz . hniels çözümü bu noktada görüntünüzü yeniden ölçeklendirmek için kullanılabilir.


2
MaximumZoomScale ve / veya minimumZoomScale :) değiştirdiğinizden emin olun.
Chris Prince

94

Diğerlerinin de açıkladığı gibi, en kolay çözüm UIImageView'unuzu bir UIScrollView'a yerleştirmektir. Bunu Interface Builder .xib dosyasında yaptım.

ViewDidLoad'da aşağıdaki değişkenleri ayarlayın. Denetleyicinizi bir UIScrollViewDelegate olacak şekilde ayarlayın.

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

Yakınlaştırmak istediğiniz imageView'e dönmek için aşağıdaki yöntemi uygulamanız gerekmektedir.

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

İOS9'dan önceki sürümlerde, bu boş temsilci yöntemini de eklemeniz gerekebilir:

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

Elma Belgeleme bunun nasıl açıklayan iyi bir iş yapar:


3
ScrollViewDidEndZooming'i silmek sorun değil: withView: şimdi, iOS9 Xcode7 ile test ettim
ElonChan 02

1
Benim için çalışıyor! scrollViewDidEndZooming :Yöntemi uygulamadan .
Johnny Zhang

48

Shefali'nin UIImageView çözümü harika çalışıyor, ancak biraz değişiklik yapılması gerekiyor:

- (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'nin çözümünün, çimdikleme sırasında sürekli ölçeklenmemesinin dezavantajı vardı. Ayrıca, yeni bir tutam başlatırken mevcut görüntü ölçeği sıfırlandı.)


Kıstırma hareketi başladıktan sonra kaydırma hareketinin etkinleştirilmesini istiyorum, bunu nasıl yapabilirim?
Gajendra K Chauhan

@Gajendra: Bu durumda, bileşenlerinizi her ikisini de kutunun dışında destekleyen bir kaydırma görünümüne yerleştirmeniz gerektiğini düşünüyorum
JRV

Ancak hem dokunma hareketi hem de kıstırma hareketi için işlevsellik istiyorum. Imageview'de de grid (katmanlar) kullandım. Kaydırma görünümünde kıstırma hareketini ve hafifçe vurma hareketini kullanmak mümkün mü?
Gajendra K Chauhan

@GajendraKChauhan: Bir kaydırma görünümü, kutudan uzaklaştırmak ve kaydırmak için sıkıştırmayı destekler - minimum / maksimum yakınlaştırma ölçeğini ayarlamayı unutmayın, ancak Brad Larsons cevabına da bakın. Ve dokunma hareketini de istiyorsanız, bunu bir hareket olarak ekleyebilirsiniz.
JRV

@JRV, self.frame.size.width'in tanınması için hangi delegeleri eklemem gerekiyor?

23

Aşağıdaki kod, UIScrollView kullanmadan UIImageView'ı yakınlaştırmaya yardımcı olur:

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

Bu en üstün çözüm :). Teşekkür.
sabiland

19

ASLA bir UIImage. HİÇ.

Bunun yerine, üzerinde yakınlaştırma ve uzaklaştırma ediyoruz viewolduğunu görüntüler UIImage.

Bu özel durumda, UIViewgörüntüyü görüntülemek için özel bir çizim içeren , sizin için görüntüyü UIImageViewgösteren veya UIWebViewyedeklemek için ek HTML'ye ihtiyaç duyan bir özel çizim oluşturmayı seçmelisiniz .

Her durumda, uygulamak gerekir touchesBegan, touchesMovedve benzeri kullanıcı (yakınlaştırma, pan, vb) yapmaya çalışıyor belirlemek için.


Açıklama için +1, hiç böyle düşünmemişti, alkış dostum
Elmo

@August, dokunuşlarda görüntüyü yakınlaştıran ve döndüren herhangi bir örnek verebilir misinizBegan, touchesMoved?
Mitesh Dobareeya

7

İşte UIWebView kullanmanızı gerektirmeyen daha önce kullandığım bir çözüm.

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

Makale şu adreste Apple Destek'te bulunabilir: http://discussions.apple.com/message.jspa?messageID=7276709#7276709


Jsp tarafından barındırılan bir destek sayfası için -1. nokta sözdiziminde yumruk sallıyor
esharp

Lütfen bana bu yöntemi nasıl arayacağımı (fareyi hareket ettirerek veya dokunarak) sağlayabilir misiniz?
Bhumesh Purohit

5

Shafali ve JRV'nin yanıtları, yakınlaştırmak için kaydırma ve kıstırma hareketlerini içerecek şekilde genişletildi:

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

Lütfen cevaplarını istedikleri zaman kaldırabilecekleri için başkalarının cevabından bahsetmekten kaçının.
Enamul Hassan

3

Bunu yapmanın en basit yolu, eğer tek istediğiniz yakınlaştırmaksa, resminizi bir içine yerleştirmektir UIWebView(az miktarda html sarıcı kodu yazın, resminize referans verin ve temelde işiniz bitti). Bunu yapmanın daha complcated yolu kullanmaktır touchesBegan, touchesMovedve touchesEndedkullanıcının parmaklarının takip etmek ve görünümünüzü en uygun özelliğini dönüşümü ayarlayın.


Cevabınızla ilgili herhangi bir örnek önerebilir misiniz? TouchesBegan, touchesMoved yöntemlerini kullanarak görüntüyü nasıl yakınlaştırabilir ve döndürebilirim. Sorum link => stackoverflow.com/questions/36833841/…
Mitesh Dobareeya

0

UIImage'ı yakınlaştırmak / uzaklaştırmak istemediğinizi unutmayın. Bunun yerine, UIImage View Controller içeren Görünümü yakınlaştırmayı / uzaklaştırmayı deneyin.

Bu soruna bir çözüm buldum. Koduma bir göz atın:

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

Not: PinchGestureRecognizer'ı bağlamayı unutmayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.