-
-
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?