MILLEN BOX

音楽好きの組み込みソフトエンジニアによるプログラミング(主にiOSアプリ開発)の勉強の記録

タッチで画像を動かして、ある特定範囲にきたら画像を吸着させる。そうでない場合は元の位置に吸着させる。 (UIImage View, UITouch, swift 1.2)

前回動かしたOasisの不朽の迷作Be Here Nowのジャケットをある範囲に持っていくと勝手に吸着させたくなりました。

Githubは以下です。

github.com

自分ポイント1

画像タッチの有効無効をviewDidLoad内でuserInteractionEnabledというpropertyで管理するようにしました。

        imageBeHereNow.userInteractionEnabled = true // 画像のタッチ操作を有効にする     
        imageDestinationArea.userInteractionEnabled = false         // 枠線部分のタッチ操作を無効にする
        imageSourceArea.userInteractionEnabled = false        // 枠線部分のタッチ操作を無効にする

自分ポイント2

タッチしたビューがUIImageViewかどうかの判断は、touchesBegan()内にてisKindOfClass(UIImageView)で判断しています。

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        ...

        // タップしたビューがUIImageViewか判断する。
        if touch.view.isKindOfClass(UIImageView) {
            isImageInside = true
        } else {
            isImageInside = false
        }
        
    }

自分ポイント3

タッチが離されたかどうかはtouchesEnded()メソッドを使って判断しています。

    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {

        ...
        
    }

自分ポイント4

吸着するアニメーションは新しくメソッドを作成しました。以下のpositonAnimationFromPoint()です。

    func positonAnimationFromPoint(fromPoint: CGPoint!, toPoint: CGPoint!) {
        let positonAnimation: CABasicAnimation = CABasicAnimation(keyPath: "position")
        positonAnimation.fromValue = NSValue(CGPoint: fromPoint)    // アニメーションの開始座標
        positonAnimation.toValue = NSValue(CGPoint: toPoint)        // アニメーションの終了位置
        positonAnimation.repeatCount = 1                            // アニメーションの繰り返し回数
        positonAnimation.duration = 0.1                             // アニメーション時間
        positonAnimation.beginTime = CACurrentMediaTime() + 0       // アニメーションの開始時間を指定
        positonAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)  // アニメーション速度の変化を指定
        imageBeHereNow.layer.addAnimation(positonAnimation, forKey: "move-layer")                           // アニメーション実行
    }

自分ポイント5

``touchesEnded()```メソッド内で自分ポイント4で作成したアニメーションメソッドを、条件に合わせて実行します。

    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
        // タッチ終了時の画像の座標と目標Areaの座標の距離を求める
        let distanceXFromDestination = fabs(imageBeHereNow.frame.origin.x - imageDestinationArea.frame.origin.x)
        let distanceYFromDestination = fabs(imageBeHereNow.frame.origin.y - imageDestinationArea.frame.origin.y)
        
        let threshold: CGFloat = 100
        
        if distanceXFromDestination < threshold && distanceYFromDestination < threshold {
            // アニメーションで目標Areaに吸着させる
            println("perform animation to imageDestinationArea")

            imageBeHereNow.layer.opacity = 1.0
            
            let fromPoint: CGPoint = imageBeHereNow.center
            let toPoint: CGPoint = imageDestinationArea.center
            positonAnimationFromPoint(fromPoint, toPoint: toPoint)
            
            imageBeHereNow.center = imageDestinationArea.center         // イメージを移動

        } else {
            // アニメーションで開始Areaに吸着させる
            println("perform animation to imageSourceArea")
            imageBeHereNow.layer.opacity = 1.0

            let fromPoint: CGPoint = imageBeHereNow.center
            let toPoint: CGPoint = imageSourceArea.center
            positonAnimationFromPoint(fromPoint, toPoint: toPoint)
 
            imageBeHereNow.center = imageSourceArea.center              // イメージを移動
        }
        
    }

もっとかっこいいやり方を教えてやってもいいぜ!って方、連絡待っております。