Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Scale) Zoom into a UIView at a point

Tags:

Something I don't understand about transformations. I want to zoom in to say the top right corner of a UIView (the main view). I use CGAffineTransformScale and have tried both setting the center/anchorPoint as well as CGAffineTransformMakeTranslation to no avail.

I can't figure out how to set the translation properly so that it will zoom in on this point.

CGAffineTransform tr = CGAffineTransformScale(self.view.transform, 2, 2);

[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
            self.view.transform = tr;
            self.view.center = CGPointMake(480,0);

} completion:^(BOOL finished) {}];
like image 382
akaru Avatar asked Mar 27 '11 02:03

akaru


2 Answers

You are setting the center of the view to the top right corner. That means you're zooming in on somewhere to the lower left of the center.

Try this

CGAffineTransform tr = CGAffineTransformScale(self.view.transform, 2, 2);
CGFloat h = self.view.frame.size.height;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
    self.view.transform = tr;
    self.view.center = CGPointMake(0,h);
} completion:^(BOOL finished) {}];

This will set the center of the blown-up view to the left bottom corner, effectively zooming in with the top right corner fixed.

This code doesn't have the height hardcoded, which is a little more portable (to an iPad of iPhone 5).

You need to first save h before setting the transform property, because after that you should not rely on the value of frame.

edit

To make it work for any scale s, use this:

CGFloat s = 3;
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
    self.view.transform = tr;
    self.view.center = CGPointMake(w-w*s/2,h*s/2);
} completion:^(BOOL finished) {}];

To make it work for bottom left, use this:

CGFloat s = 3;
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
    self.view.transform = tr;
    self.view.center = CGPointMake(w*s/2,h-h*s/2);
} completion:^(BOOL finished) {}];

To make it work for bottom right, use this:

CGFloat s = 3;
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
    self.view.transform = tr;
    self.view.center = CGPointMake(w-w*s/2,h-h*s/2);
} completion:^(BOOL finished) {}];

See also: How to scale (zoom) a UIView to a given CGPoint

like image 129
mvds Avatar answered Nov 09 '22 15:11

mvds


In case anyone is still interested, here is the Swift 3.0 solution, to which I added the possibility to fade out correctly.

(I know there are two enums missing, but the code is still readable and I think you will get the concept)

func animateZoom(direction: ZoomDirection, type: ZoomType, duration: Double = 0.3, scale: CGFloat = 1.4) {
    var cx, cy: CGFloat
    var tr: CGAffineTransform = CGAffineTransform.identity

    if (type == .IN) { tr = self.transform.scaledBy(x: scale, y: scale) }

    let h: CGFloat = self.frame.size.height;
    let w: CGFloat = self.frame.size.width;

    if (type == .IN) {
        switch direction {
        case .LEFT_DOWN:
            cx = w*scale/2
            cy = h-h*scale/2
            break
        case .LEFT_UP:
            cx = w*scale/2
            cy = h*scale/2
            break
        case .RIGHT_UP:
            cx = w-w*scale/2
            cy = h*scale/2
            break
        case .RIGHT_DOWN:
            cx = w-w*scale/2
            cy = h-h*scale/2
            break
        }
    } else {
        cx = w/scale/2
        cy = h/scale/2
    }

    UIView.animate(withDuration: duration, delay: 0, options: [.curveEaseInOut], animations: {
        self.transform = tr
        self.center = CGPoint(x: cx, y: cy)
    }, completion: { finish in })
}
like image 40
Nighthawk Avatar answered Nov 09 '22 14:11

Nighthawk