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) {}];
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
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 })
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With