Proper transform for scaling a UIView from a rect?
Asked Answered
T

3

10

I want to mimic "zooming in" on a view. The larger view will be added as a subview to the smaller view's superview, and the larger view should look as if it is zooming in from the smaller view. Given the rect of the smaller view fromRect and the final frame of the zoomed in larger view finalRect, what would be the proper transform?

enter image description here

I imagine the method signature would be like the following, with view being the superview. I wrote this up to help myself, but cannot figure it out yet.

-(CGAffineTransform) translatedAndScaledTransformUsingViewRect:(CGRect)viewRect fromRect:(CGRect)fromRect inView:(UIView*) view
{
//calculate the scaling based on the final frame of viewToBeStretched (viewRect) vs the "fromRect"
CGFloat scaleX = ?, scaleY = ?;
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scaleX, scaleY);

//use translation instead of modifying the view's center, since frame changes with transforms are no good
CGFloat translationX = ?, translationY =?;
CGAffineTransform translationTransform = CGAffineTransformMakeTranslation(translationX, translationY);

CGAffineTransform final = CGAffineTransformConcat(scaleTransform, translationTransform);

return final;
}
Turbulent answered 29/1, 2013 at 23:51 Comment(4)
You know, for the scales, it's just a matter of dividing the final lengths of the rect you wish to size it up to by the current size of the view. The translations are a little harder.Krasnoyarsk
@Krasnoyarsk right, I could do just the scaling but didn't want to pollute the example here. I could easily just set the center property to the center of the smaller view, but that doesn't work with transforms.Turbulent
The piece of code that you posted here seems to be correct, so what exactly does not work?Sourwood
Anyway, I suggest to add the larger view to your superview pre-transformed so that it exactly covers the smaller view as soon as the user clicks on it. Then you reset the the transformation matrix to identity matrix with an animation so as a result it will pop out from the place of the small view.Sourwood
E
21

So actual implementation is very simple:

- (CGAffineTransform)translatedAndScaledTransformUsingViewRect:(CGRect)viewRect fromRect:(CGRect)fromRect {

    CGSize scales = CGSizeMake(viewRect.size.width/fromRect.size.width, viewRect.size.height/fromRect.size.height);
    CGPoint offset = CGPointMake(CGRectGetMidX(viewRect) - CGRectGetMidX(fromRect), CGRectGetMidY(viewRect) - CGRectGetMidY(fromRect));
    return CGAffineTransformMake(scales.width, 0, 0, scales.height, offset.x, offset.y);

}

You can see full example here: https://github.com/vGubriienko/TransformTest

(I still need update it to use identity as full image)

Edmonson answered 8/2, 2013 at 1:27 Comment(0)
S
2

If you're only dealing with images, you can take advantage of the UIImageView's contentMode property and set it to UIViewContentModeScaleAspectFill. Then you can just do a [UIView transitionWithView:] and set the frame of your UIImageView to your final CGRect (or your whole screen because it will fill correctly). It will do the zooming-in effect you're looking for.

The best way to do this is to create a copy of the UIImageView as a subview of your superview and place it right on top of the original UIImageView and perform the transformations from there.

I wrote some functions to extend it to a UITableViewController a while back which lets you zoom-in on any UIImageView with a fade to black and zoom transition and the final image is zoomable and can be dismissed.

https://github.com/PeterCen/iOS-Image-Presenter/

Simmer answered 30/1, 2013 at 1:34 Comment(1)
Nicely done, but I need to do this using transforms, as this will be a view controller transition--thus the vc must be smaller at first. Your example assumes the UIImageView will take care of its content.Turbulent
T
1

Turns out the best solution was to create a transform manually using a matrix.

Turbulent answered 8/2, 2013 at 1:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.