PanGestureの実装の注意点

PanGestureの実装方法が間違っているのに最近気づいたため、備忘録として残します。

<h2>一つViewを作る</h2>

```ViewController.swift
import UIKit

class ViewController: UIViewController {

    let blueView = {
        let view = UIView()
        view.backgroundColor = .blue
        
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(blueView)
        
        
    }
    
    override func viewDidLayoutSubviews() {
        blueView.frame = CGRect(x: 30, y: 30, width: 100, height: 50)
    }
}

```

<H2>次にPanGestureをつける</H2>

私はこんな感じで実装していました。一応動きます。

```ViewController.swift

import UIKit

class ViewController: UIViewController {
    
    let blueView = {
        let view = UIView()
        view.backgroundColor = .blue
        
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //追加
        blueView.isUserInteractionEnabled = true
        
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture))
        blueView.addGestureRecognizer(panGesture)
        
        view.addSubview(blueView)
    }
    
    override func viewDidLayoutSubviews() {
        blueView.frame = CGRect(x: 30, y: 30, width: 100, height: 50)
    }

    //追加
    @objc func panGesture(sender: UIPanGestureRecognizer){
        let point = sender.location(in: view)
        let panGesture = sender.view
        panGesture?.center = point
        
    }
    
}

```

ただこれだとViewが小さいときは気にならないのですが、viewのサイズが大きい時(width :300, height:300くらい）ぎこちない動きになります。原因はこのpanGestureメソッドです。

```swift
@objc func panGesture(sender: UIPanGestureRecognizer){

        //①クリックした地点の座標を取得
        let point = sender.location(in: view)
        let panGesture = sender.view
        
        //②viewの中心座標をクリックした地点の座標に無理やり設定している
        panGesture?.center = point
        
    }

```


<h2>移動量を使おう</h2>
メソッドを以下のように変更するとスムーズに移動します。

```swift
@objc func panGesture(sender: UIPanGestureRecognizer){

        //viewをドラッグした時の移動量を取得
        let move = sender.translation(in: view)
        
        let panGesture = sender.view
        
        //移動量をviewの中心のx座標、y座標に足してあげます
        panGesture?.center.x += move.x
        panGesture?.center.y += move.y
        
        //最後に移動量をリセットしてあげます。この文がないとviewがどこかに飛んでいきます。
        sender.setTranslation(.zero, in: view)
        
    }
```

<H2>全体のコード</H2>

```swift
import UIKit

class ViewController: UIViewController {
    
    let blueView = {
        let view = UIView()
        view.backgroundColor = .blue
        
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        blueView.isUserInteractionEnabled = true
        
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture))
        blueView.addGestureRecognizer(panGesture)
        
        view.addSubview(blueView)
    }
    
    override func viewDidLayoutSubviews() {
        blueView.frame = CGRect(x: 30, y: 30, width: 300, height: 300)
    }

    
    @objc func panGesture(sender: UIPanGestureRecognizer){
        let move = sender.translation(in: view)
        
        let panGesture = sender.view
        
        panGesture?.center.x += move.x
        panGesture?.center.y += move.y
        
        sender.setTranslation(.zero, in: view)
        
    }
    
}
```