วิธีการย่อ / ขยายวัตถุ UIImage เมื่อผู้ใช้ตรึงหน้าจอ?


84

ฉันต้องการซูมเข้า / ออกวัตถุ UIImage เมื่อผู้ใช้ดำเนินการหยิกมาตรฐานบนแอปพลิเคชันของฉัน ฉันกำลังใช้ UIImageView เพื่อแสดงภาพของฉันหากรายละเอียดนั้นช่วยได้ในทางใดทางหนึ่ง

ฉันกำลังพยายามหาวิธีทำ แต่ก็ยังไม่มีโชค

เบาะแสใด ๆ ?

คำตอบ:


85

อีกวิธีง่ายๆในการทำเช่นนี้คือการจัดวางUIImageViewไฟล์UIScrollView. ดังที่ฉันอธิบายไว้ที่นี่คุณต้องตั้งค่า 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

โซลูชันของ Shefali สำหรับ UIImageView ใช้งานได้ดี แต่ต้องมีการปรับเปลี่ยนเล็กน้อย:

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

@Gajendra: ในกรณีนั้นฉันคิดว่าคุณควรใช้การฝังส่วนประกอบของคุณในมุมมองแบบเลื่อนซึ่งรองรับทั้งสองอย่างนอกกรอบ
JRV

แต่ฉันต้องการฟังก์ชันสำหรับทั้งท่าทางการแตะและการบีบนิ้ว ฉันยังใช้เส้นตาราง (เลเยอร์) บน Imageview ฉันขอทราบเป็นไปได้ไหมที่จะใช้ท่าทางบีบนิ้วและแตะท่าทางในมุมมองเลื่อน
Gajendra K Chauhan

@GajendraKChauhan: มุมมองแบบเลื่อนรองรับการบีบนิ้วเพื่อซูมและแพนออกจากกรอบ - อย่าลืมตั้งค่าระดับการซูมต่ำสุด / สูงสุด แต่ดูที่คำตอบของ Brad Larsons ด้วย และหากคุณต้องการท่าทางสัมผัสด้วยคุณสามารถเพิ่มสิ่งนั้นเป็นท่าทางสัมผัสได้
JRV

@JRV ฉันต้องเพิ่มผู้รับมอบสิทธิ์อะไรเพื่อให้รู้จัก self.frame.size.width

23

โค้ดด้านล่างช่วยในการซูม UIImageView โดยไม่ต้องใช้ 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;
    }
}

นี่คือทางออกที่ดีที่สุด :) ขอบคุณ.
sabiland

19

โปรดทราบว่าคุณไม่เคยซูมเข้าบนไฟล์UIImage. เคย.

แต่คุณกำลังซูมเข้าและออกจากส่วนviewที่แสดงไฟล์UIImage.

ในกรณีนี้คุณควรเลือกที่จะสร้างแบบกำหนดเองUIViewด้วยการวาดแบบกำหนดเองเพื่อแสดงภาพUIImageViewซึ่งจะแสดงภาพให้คุณหรือUIWebViewต้องใช้ HTML เพิ่มเติมเพื่อสำรองข้อมูล

ในทุกกรณีที่คุณจะต้องดำเนินการtouchesBegan, touchesMovedและชอบที่จะตรวจสอบสิ่งที่ผู้ใช้จะพยายามที่จะทำ (ซูมกระทะ ฯลฯ )


+1 สำหรับการชี้แจงไม่เคยคิดแบบนั้นมาก่อนเชียร์เพื่อน
Elmo

@ สิงหาคมคุณช่วยให้ฉันมีตัวอย่างที่ซูมและหมุนภาพบนสัมผัสได้ไหม
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


-1 สำหรับหน้าการสนับสนุนที่โฮสต์ jsp เขย่าหมัดที่ไวยากรณ์ dot
esharp

คุณช่วยบอกวิธีเรียกวิธีนี้ได้ไหม (เมื่อเลื่อนเมาส์หรือสัมผัส)
ภูมิเดชปุโรหิต

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

3

วิธีที่ง่ายที่สุดในการทำสิ่งนี้หากสิ่งที่คุณต้องการคือการซูมด้วยนิ้วมือคือการวางภาพของคุณไว้ในช่องUIWebView(เขียนโค้ด html wrapper จำนวนเล็กน้อยอ้างอิงภาพของคุณและคุณก็ทำเสร็จแล้ว) วิธี complcated มากขึ้นในการทำเช่นนี้คือการใช้touchesBegan, touchesMovedและtouchesEndedการติดตามของนิ้วมือของผู้ใช้และปรับมุมมองของคุณเปลี่ยนคุณสมบัติเหมาะสม


คุณช่วยแนะนำตัวอย่างที่เกี่ยวข้องกับคำตอบของคุณให้ฉันได้ไหม ฉันจะซูมและหมุนภาพโดยใช้วิธี TouchBegan, TouchMoved ได้อย่างไร ลิงค์คำถามของฉัน => stackoverflow.com/questions/36833841/…
Mitesh Dobareeya

0

โปรดทราบว่าคุณไม่ต้องการซูมเข้า / ออก UIImage ให้พยายามย่อ / ขยายมุมมองซึ่งมี UIImage View Controller แทน

ฉันได้แก้ปัญหาสำหรับปัญหานี้แล้ว ดูรหัสของฉัน:

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