コード
参考にした記事
https://medium.com/@jeremysh/instagram-pinch-to-zoom-pan-gesture-tutorial-772681660dfe
var isZooming = false
var originalImageCenter:CGPoint?
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(self.pinch(sender:)))
pinch.delegate = self
self.photoScrollView.addGestureRecognizer(pinch)
let pan = UIPanGestureRecognizer(target: self, action: #selector(self.pan(sender:)))
pan.delegate = self
self.photoScrollView.addGestureRecognizer(pan)
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
@objc func pinch(sender: UIPinchGestureRecognizer) {
delegate?.didPinch()
if sender.state == .began {
let currentScale = self.photoScrollView.frame.size.width / self.photoScrollView.bounds.size.width
let newScale = currentScale * sender.scale
if newScale > 1 {
self.isZooming = true
}
} else if sender.state == .changed {
guard let view = sender.view else { return }
let pinchCenter = CGPoint(x: sender.location(in: view).x - view.bounds.midX,
y: sender.location(in: view).y - view.bounds.midY)
let transform = view.transform.translatedBy(x: pinchCenter.x, y: pinchCenter.y)
.scaledBy(x: sender.scale, y: sender.scale)
.translatedBy(x: -pinchCenter.x, y: -pinchCenter.y)
let currentScale = self.photoScrollView.frame.size.width / self.photoScrollView.bounds.size.width
var newScale = currentScale * sender.scale
if newScale < 1 {
newScale = 1
let transform = CGAffineTransform(scaleX: newScale, y: newScale)
self.photoScrollView.transform = transform
sender.scale = 1
} else {
view.transform = transform
sender.scale = 1
}
} else if sender.state == .ended || sender.state == .failed || sender.state == .cancelled {
delegate?.didFinishPinch()
guard let center = self.originalImageCenter else {return}
UIView.animate(withDuration: 0.3, animations: {
self.photoScrollView.transform = CGAffineTransform.identity
self.photoScrollView.center = center
}, completion: { _ in
self.isZooming = false
})
}
}
@objc func pan(sender: UIPanGestureRecognizer) {
if self.isZooming && sender.state == .began {
self.originalImageCenter = sender.view?.center
} else if self.isZooming && sender.state == .changed {
let translation = sender.translation(in: self)
if let view = sender.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y + translation.y)
}
sender.setTranslation(CGPoint.zero, in: self.photoScrollView.superview)
}
}
あとはdelegateをcollectionViewControllerまで引っ張っていった。
func didPinch() {
collectionView.isScrollEnabled = false
}
func didFinishPinch() {
collectionView.isScrollEnabled = true
}