it-swarm.dev

Kullanıcı ekranı sıkıştırdığında UIImage nesnesini nasıl yakınlaştırıp/uzaklaştırırım?

Kullanıcı uygulamamda standart sıkıştı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ı oluyorsa, resmimi görüntülemek için şu anda bir UIImageView kullanıyorum.

Bunu nasıl yapacağımı anlamaya çalışıyorum, ama şu ana kadar böyle bir şans yok.

Herhangi bir ipucu var mı?

78
jpm

Bunu yapmanın başka bir kolay yolu UIImageView'ınızı UIScrollView içine yerleştirmektir. Burada açıkladığım gibi , kaydırma görünümünün contentSize öğesini UIImageView's boyutunuzla aynı olacak şekilde ayarlamanız gerekir. Denetleyici örneğinizi kaydırma görünümünün temsilcisi olacak şekilde ayarlayın ve çimdik yakınlaştırma ve görüntü kaydırma için viewForZoomingInScrollView: ve scrollViewDidEndZooming:withView:atScale: yöntemlerini uygulayın. Bu, Ben'in çözümünün tam bir web görünümünün ek yüküne sahip olmadığınızdan, sadece biraz daha hafif bir şekilde yaptığı gibi etkilidir.

Karşılaştığınız sorunlardan biri, kaydırma görünümündeki ölçeklendirmenin görüntüye uygulanan dönüştürmeler biçiminde gelmesidir. Bu, yüksek zoom faktörlerinde bulanıklığa yol açabilir. Yeniden çizilebilecek bir şey için, tutam hareketi bittikten sonra daha net bir görüntü sağlamak için önerilerimi burada uygulayabilirsiniz. Bu noktada hniels'in çözümü görüntünüzü yeniden ölçeklendirmek için kullanılabilir.

83
Brad Larson

Açıklandığı gibi, en kolay çözüm UIImageView'ınızı 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 olarak 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'ı döndürmek için aşağıdaki yöntemi uygulamanız gerekir.

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

Apple Belgeleri bunun nasıl yapılacağını açıklayan iyi bir iş çıkarır:

88
rogue

Shefali'nin UIImageView için çözümü harika çalışıyor, ancak küçük bir değişiklik gerektiriyor:

- (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ü, kısma sırasında sürekli olarak ölçeklenmediğini olumsuz yönde etkiliyor. Ayrıca, yeni bir kısma başladığında mevcut görüntü ölçeği sıfırlandı.)

47
JRV

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;
    }
}
23
Shefali Soni

Asla bir UIImage üzerinde yakınlaştırmayacağınızı unutmayın. HİÇ.

Bunun yerine, view öğesini görüntüleyen UIImage öğesini yakınlaştırır ve uzaklaştırırsınız.

Bu özel durumda, görüntüyü görüntülemek için özel çizim içeren özel bir UIView__, görüntüyü sizin için görüntüleyen UIImageView veya yedeklemesi için ek bir HTML'ye ihtiyaç duyacak UIWebView oluşturmayı seçmelisiniz.

Her durumda, kullanıcının ne yapmaya çalıştığını belirlemek için touchesBegan, touchesMoved ve benzerlerini uygulamanız gerekir (yakınlaştırma, kaydırma vb.).

19
August

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

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

Bu makale Apple Destek'te bulunabilir: http://discussions.Apple.com/message.jspa?messageID=7276709#7276709

8
Niels Hansen

Shafali ve JRV'nin cevapları, yakınlaştırmak için kaydırma ve çimdik 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;
    }
}
5
paul king

Bunu yapmanın en basit yolu, istediğiniz tek şey sıkıştırma yakınlaştırma ise, resminizi UIWebView içine yerleştirmektir (küçük miktarda html sarmalayıcı kodu yazın, resminize başvuru yapın ve temel olarak tamamlayın). Bunu yapmanın daha karmaşık yolu, kullanıcının parmaklarını takip etmek için touchesBegan, touchesMoved ve touchesEnded kullanmak ve görünümünüzün dönüştürme özelliğini uygun şekilde ayarlamaktır.

3
Ben Gottlieb

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

Bu problem için bir çözüm yaptım. Koduma bir bak:

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

0
G Azam