Skip to content

Instantly share code, notes, and snippets.

@TimOliver
Last active November 23, 2022 09:14
Show Gist options
  • Save TimOliver/71be0a8048af4bd86ede to your computer and use it in GitHub Desktop.
Save TimOliver/71be0a8048af4bd86ede to your computer and use it in GitHub Desktop.
Zooming to a specific CGPoint inside a UIScrollView (2015 Edition)
@implementation UIScrollView (ZoomToPoint)
/**
Zooms into the specified point of the scroll view's zoomable content view at the supplied scaled.
(The zoomable content view is the view that is returned in `viewForZoomingInScrollView:`
@param zoomPoint - In terms of the scroll view's co-ordinate space, the point to zoom to
@param scale - A value between minimumZoomScale and maximumZoomScale in which to zoom to.
@param animated - Whether the transition is animated, or instant
*/
- (void)zoomToPoint:(CGPoint)zoomPoint withScale:(CGFloat)scale animated:(BOOL)animated
{
//Ensure scale is clamped to the scroll view's allowed zooming range
scale = MIN(scale, self.maximumZoomScale);
scale = MAX(scale, self.minimumZoomScale);
//`zoomToRect` works on the assumption that the input frame is in relation
//to the content view when zoomScale is 1.0
//Work out in the current zoomScale, where on the contentView we are zooming
CGPoint translatedZoomPoint = CGPointZero;
translatedZoomPoint.x = zoomPoint.x + self.contentOffset.x;
translatedZoomPoint.y = zoomPoint.y + self.contentOffset.y;
//Figure out what zoom scale we need to get back to default 1.0f
CGFloat zoomFactor = 1.0f / self.zoomScale;
//By multiplying by the zoom factor, we get where we're zooming to, at scale 1.0f;
translatedZoomPoint.x *= zoomFactor;
translatedZoomPoint.y *= zoomFactor;
//work out the size of the rect to zoom to, and place it with the zoom point in the middle
CGRect destinationRect = CGRectZero;
destinationRect.size.width = CGRectGetWidth(self.frame) / scale;
destinationRect.size.height = CGRectGetHeight(self.frame) / scale;
destinationRect.origin.x = translatedZoomPoint.x - (CGRectGetWidth(destinationRect) * 0.5f);
destinationRect.origin.y = translatedZoomPoint.y - (CGRectGetHeight(destinationRect) * 0.5f);
if (animated) {
[UIView animateWithDuration:0.55f delay:0.0f usingSpringWithDamping:1.0f initialSpringVelocity:0.6f options:UIViewAnimationOptionAllowUserInteraction animations:^{
[self zoomToRect:destinationRect animated:NO];
} completion:^(BOOL completed) {
if ([self.delegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) {
[self.delegate scrollViewDidEndZooming:self withView:[self.delegate viewForZoomingInScrollView:self] atScale:scale];
}
}];
}
else {
[self zoomToRect:destinationRect animated:NO];
}
}
@end
@kmaschke85
Copy link

Sorry @01GOD can't tell. It's animating fine for me. Can you provide an example where it's not working for you?

@01GOD
Copy link

01GOD commented Sep 16, 2022

@kmaschke85 Seems there is an issue with the UIView animation system in that app not animating. I built a custom animator for that today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment