-
-
Save TimOliver/71be0a8048af4bd86ede to your computer and use it in GitHub Desktop.
@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 |
Great job, Man!
@umangbista Use a UITapGestureRecognizer
. :)
@ValentinFesenko Thanks a lot man! :)
Hi, how can I scroll from 0, 0 position to particular points using above code?
Thanks works really great!!!
Here a swift version of your code:
extension UIScrollView {
func zoom(toPoint zoomPoint : CGPoint, scale : CGFloat, animated : Bool) {
var scale = CGFloat.minimum(scale, maximumZoomScale)
scale = CGFloat.maximum(scale, self.minimumZoomScale)
var translatedZoomPoint : CGPoint = .zero
translatedZoomPoint.x = zoomPoint.x + contentOffset.x
translatedZoomPoint.y = zoomPoint.y + contentOffset.y
let zoomFactor = 1.0 / zoomScale
translatedZoomPoint.x *= zoomFactor
translatedZoomPoint.y *= zoomFactor
var destinationRect : CGRect = .zero
destinationRect.size.width = frame.width / scale
destinationRect.size.height = frame.height / scale
destinationRect.origin.x = translatedZoomPoint.x - destinationRect.width * 0.5
destinationRect.origin.y = translatedZoomPoint.y - destinationRect.height * 0.5
if animated {
UIView.animate(withDuration: 0.55, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.6, options: [.allowUserInteraction], animations: {
self.zoom(to: destinationRect, animated: false)
}, completion: {
completed in
if let delegate = self.delegate, delegate.responds(to: #selector(UIScrollViewDelegate.scrollViewDidEndZooming(_:with:atScale:))), let view = delegate.viewForZooming?(in: self) {
delegate.scrollViewDidEndZooming!(self, with: view, atScale: scale)
}
})
} else {
zoom(to: destinationRect, animated: false)
}
}
}
@kmaschke85 Thanks works great!
@kmaschke85
Thanks, but it isn't animating. Happen to know why? Thanks in advance!
@kmaschke85 Thanks for posting that, but it isn't animating for some reason. Happen to know how to solve that?
Thanks in advance for explaining!
Sorry @01GOD can't tell. It's animating fine for me. Can you provide an example where it's not working for you?
@kmaschke85 Seems there is an issue with the UIView animation system in that app not animating. I built a custom animator for that today.
Thanks works really great!!! Here a swift version of your code:
extension UIScrollView { func zoom(toPoint zoomPoint : CGPoint, scale : CGFloat, animated : Bool) { var scale = CGFloat.minimum(scale, maximumZoomScale) scale = CGFloat.maximum(scale, self.minimumZoomScale) var translatedZoomPoint : CGPoint = .zero translatedZoomPoint.x = zoomPoint.x + contentOffset.x translatedZoomPoint.y = zoomPoint.y + contentOffset.y let zoomFactor = 1.0 / zoomScale translatedZoomPoint.x *= zoomFactor translatedZoomPoint.y *= zoomFactor var destinationRect : CGRect = .zero destinationRect.size.width = frame.width / scale destinationRect.size.height = frame.height / scale destinationRect.origin.x = translatedZoomPoint.x - destinationRect.width * 0.5 destinationRect.origin.y = translatedZoomPoint.y - destinationRect.height * 0.5 if animated { UIView.animate(withDuration: 0.55, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.6, options: [.allowUserInteraction], animations: { self.zoom(to: destinationRect, animated: false) }, completion: { completed in if let delegate = self.delegate, delegate.responds(to: #selector(UIScrollViewDelegate.scrollViewDidEndZooming(_:with:atScale:))), let view = delegate.viewForZooming?(in: self) { delegate.scrollViewDidEndZooming!(self, with: view, atScale: scale) } }) } else { zoom(to: destinationRect, animated: false) } } }
👍🏼
How to implement double tap zoom using this code?