LoginSignup
27
29

More than 5 years have passed since last update.

Swiftで固いアルバムのようなアニメーションを作る

Last updated at Posted at 2016-05-30

iOSでのデフォルトのページビューはぺらぺらの紙のようなアニメーションですが、固いアニメーションをつくる方法を紹介します

まずはデモ

a.mov-compressor.gif

つくり方

基本的には、CATransform3DRotateを使ってLayerを回転させていきます
座標空間は図のようになっているため、今回はy軸を中心に回転させます
スクリーンショット 2016-05-30 11.54.34.png

view.layer.transform = CATransform3DRotate(transform2, CGFloat(M_PI), 0, 1, 0)

このままだと、下図のようにViewの中心で回転してしまい、片開きの本に見えなくなってしまいます
スクリーンショット 2016-05-30 12.00.18.png

左端を中心に回転させるには

view.layer.anchorPoint = CGPoint(x:0, y:0.5)

を設定します。この設定を入れると、水平方向にViewの幅の1/2分右にずれて表示されるため、X軸にCATransform3DTranslate(CATransform3DIdentity, -width/2, 0, 0)をあらかじめ設定し修正します。

transformを設定した状態で、UIView.Animationを使いCATransform3DRotate(transform2, CGFloat(M_PI), 0, 1, 0)を使って回転させると、移動と回転が同時に起きてしまい、綺麗なアニメーションになりません。

スクリーンショット 2016-05-30 12.08.55.png

対策として、ビューを入れ子にし、外側のビューをx軸で-width/2分offsetさせます。ここまでのコードで裏面のない、固いアニメーションは動くはずです。

裏面を作る方法

あらかじめ、CATransform3DRotate(CATransform3DIdentity, CGFloat(M_PI), 0, 1, 0)として裏返すことで裏面を作ることができますが、この場合は、アンカーポイントがCGPoint(x:0, y:0.5)である必要があるため、さらに入れ子にします。

スクリーンショット 2016-05-30 12.18.06.png
赤枠のビューをあらかじめ、裏返し、緑枠のビューをアニメーションさせることで裏面を作ることができますが、表面が裏返った時にも表示されてしまいます。裏返った時に自動的に非表示にするには、表面に対してView?.layer.doubleSided = falseを指定します。

カメラとの距離

Y軸回転させた場合、3D的な意味でのカメラは正面から撮影しますが、この時のViewとカメラの距離は
transform.mc34で設定します。3000を小さくすると近づき、大きくすると遠ざかります。
この値は微調整しながら、お好みの数字にしてください。
回転させる時のコードは下記のようになります。

 var transform = CATransform3DIdentity
 transform.m34 = 1/3000
 transform = CATransform3DRotate(transform, -CGFloat(M_PI), 0, 1, 0)

まとめ

ビューの構造と初期値
スクリーンショット 2016-05-30 12.28.49.png

緑のビューのアニメーションコード

UIView.animateWithDuration(0.8, animations: {
            var transform = CATransform3DIdentity
            transform.m34 = 1/3000
            transform = CATransform3DRotate(transform, -CGFloat(M_PI), 0, 1, 0)
            self.faceView?.layer.transform = transform

            var transform2 = CATransform3DIdentity
            transform2.m34 = 1/3000
            transform2 = CATransform3DRotate(transform2, CGFloat(M_PI), 0, 1, 0)
            self.backView?.layer.transform = transform2

        })
27
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
29