【Swift】ピンチイン・アウト・ダブルタップで画像を拡大する1(UIScrollView使用バージョン)

ピンチイン・アウトとダブルタップで画像(UIImageView)を拡大する方法です
UIScrollViewにUIImageViewを設置する形で実装します

ズーム後の位置の補正はこちらを参考にさせていただきました
【iOS開発】UIScrollViewでピンチイン/アウトによる拡大縮小: ポケットのなかにはCDRがひとつ

class MainView: UIView, UIScrollViewDelegate {
    
    var scrollView: UIScrollView! = nil
    var imageView: UIImageView! = nil
    
    var isDoubleTap: Bool = false

    override init(frame: CGRect) {
        super.init(frame: frame)
        
        myInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        myInit()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        scrollView.frame = self.bounds
        imageView.frame = scrollView.bounds
    }
    
    /// 初期化
    func myInit() {
        
        // ScrollViewを作成
        scrollView = UIScrollView()
        scrollView.minimumZoomScale = 1
        scrollView.maximumZoomScale = 5
        scrollView.scrollEnabled = true
        scrollView.zoomScale = 1
        scrollView.contentSize = self.bounds.size
        scrollView.delegate = self
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        scrollView.backgroundColor = UIColor.blackColor()
        self.addSubview(scrollView)
        
        // 画像を作成
        let image = UIImage(named: "photo")
        imageView = UIImageView(image: image)
        imageView.userInteractionEnabled = true // 画像がタップできるようにする
        imageView.contentMode = UIViewContentMode.ScaleAspectFit
        scrollView.addSubview(imageView)
        
        // ダブルタップの準備
        let doubleTapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self
            , action:#selector(doubleTap(_:)))
        doubleTapGesture.numberOfTapsRequired = 2
        imageView.addGestureRecognizer(doubleTapGesture)
    }
    
    // MARK: - UIScrollViewDelegate
    
    /// ズームしたいUIViewを返す
    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        
        return imageView
    }
    
    /// ズーム変更
    func scrollViewDidZoom(scrollView: UIScrollView) {
        
        self.updateImageCenter()
    }
    
    /// ズーム完了
    func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat) {
        
        self.updateImageCenter() 
        isDoubleTap = false
    }
    
    //MARK: -
    
    /// ダブルタップ
    func doubleTap(gesture: UITapGestureRecognizer) -> Void {
        
        if ( scrollView.zoomScale < scrollView.maximumZoomScale ) {
            
            isDoubleTap = true
            
            var tapPoint = gesture.locationInView(gesture.view)
            tapPoint.x /= scrollView.zoomScale
            tapPoint.y /= scrollView.zoomScale
            
            let newScale:CGFloat = scrollView.zoomScale * 2
            let zoomRect:CGRect = zoomRectForScale(newScale, center: tapPoint)
            scrollView.zoomToRect(zoomRect, animated: true)
            
        } else {
            // 最初のサイズに戻す
            scrollView.setZoomScale(1.0, animated: true)
        }
    }
    
    /// ズーム時の矩形を求める
    /// - parameter scale: 拡大率
    /// - parameter center: 中央の座標
    /// - returns: ズーム後の表示エリア
    func zoomRectForScale(scale:CGFloat, center: CGPoint) -> CGRect{
        
        var zoomRect: CGRect = CGRect()
        zoomRect.size.height = self.frame.size.height / scale
        zoomRect.size.width = self.frame.size.width / scale
        
        zoomRect.origin.x = center.x - zoomRect.size.width / 2.0
        zoomRect.origin.y = center.y - zoomRect.size.height / 2.0
        
        return zoomRect
    }
    
    /// ズーム後の画像の位置を調整する
    func updateImageCenter() {
        
        // ダブルタップした場合はこの処理を行わない
        if isDoubleTap {
            return
        }
        let image = imageView.image
        
        // UIViewContentMode.ScaleAspectFit時のUIImageViewの画像サイズを求める
        let frame = AVMakeRectWithAspectRatioInsideRect(image!.size, imageView.bounds)
        
        var imageSize = CGSizeMake(frame.size.width, frame.size.height)
        imageSize.width *= scrollView.zoomScale
        imageSize.height *= scrollView.zoomScale
        
        var point: CGPoint = CGPointZero
        point.x = imageSize.width / 2
        if imageSize.width < scrollView.bounds.width {
            point.x += (scrollView.bounds.width - imageSize.width) / 2
        }
        point.y = imageSize.height / 2
        if imageSize.height < scrollView.bounds.height {
            point.y += (scrollView.bounds.height - imageSize.height) / 2
        }
        imageView.center = point
    }
}

この実装では、ピンチイン・ピンチアウトでの拡大縮小は問題ありませんが、ダブルタップでの拡大の動作がイマイチです

今回の実装ではこんな動き
ピンチイン・アウト・ダブルタップで画像を拡大する(UIScrollViewを使用)

理想はこれ
ピンチイン・アウト・ダブルタップで画像を拡大する(UIScrollViewを使用)

今回の実装では、ダブルタップした位置が画面の中央に移動するので、同じ場所を再度拡大したい時は指を動かさないといけません。できればトントン・トントンと連続でタップすれば同じ場所が拡大してほしいところ。

というわけで、別の方法を考えます

追記)ダブルタップ位置の問題を解決したバージョンの記事を書きました

前回UIScrollViewを使った画像拡大の実装方法を書きましたが、今回は別の方法で実装してみます 今回の実装では、前回の不...
関連コンテンツ
ブログランキング
  • にほんブログ村 教育ブログ プログラミング教育へ
  • にほんブログ村 子育てブログ 子供の習い事(教室・業者)へ

  • スポンサーリンク
    Google336 記事下
    Google336 記事下

    シェアする

    • このエントリーをはてなブックマークに追加

    フォローする

    スポンサーリンク
    Google336 記事下
    トップへ戻る