[iOS] UITableViewでパララックス効果を試して見た
1 はじめに
奥行きや遠近感のことをパララックス(Parallax)「視差効果」と言います。
アプリやWebページで、スクロールなどの動作に応じて、レイヤ毎に異なるスピードで動かすことで立体感や奥行きを演出する手法を、パララックス効果と呼びます。
今回は、iPhoneのテーブルビューで、この手法を実装してみました。
作業の手順は、次の4つです。
- 画像を表示する枠ビューを用意する
- 枠ビューより大きなサイズの画像ビューを用意する
- スクロール時に、セルのオフセットを取得する
- セルのオフセットに応じて枠ビュー上の画像ビューのオフセットを変化させる
そして、下記が、動作しているようするです。
2 実装
(1) 画像を表示する枠ビューを用意する
最初にUITableCellの、Row Heightを固定値で指定しました。 そして、その中に、上下左右に10ptの制約を指定したビューを置きます。 これが、枠ビューとなります。(ここからイメージビュー(画像)を覗き込む感じです。)
(2) 枠ビューより大きなサイズの画像ビューを用意する
上で作成した枠ビューの中に、UIImageViewを置き、左右を 0pt そして、上下に -50pt を制約を指定します。
結果的に、UIImageViewは、枠ビューから上下にはみ出した状態になります。
続いて、枠ビューのClio To Boundsにチェックを入れて、枠ビューからはみ出た部分は、見えなくなるようにします。
ここまでの作業で、UIImageViewのオフセットを0〜-100に変化させることで、枠から覗き込める画像が上下にスライドするのが確認できます。
(3) スクロール時に、セルのオフセットを取得する
UITableViewのスクロールは、scrollViewDidScroll(_:)で取得が可能です。
インデックスから当該セルのFrameを取得し(①)、これを親となるUITableViewの相対位置に変換し(②)、セルの中心が、親テーブルのどの位置(0〜1.0で表現)になるかを算出しています。(③)
override func scrollViewDidScroll(_ scrollView: UIScrollView) { for index in tableView.indexPathsForVisibleRows! { let cell = tableView.cellForRow(at: index) as! TableViewCell let rect = tableView.rectForRow(at:index) // ① let rectInTable = tableView.convert(rect, to: tableView.superview) // ② let offset = rectInTable.origin.y + rectInTable.height / 2 // ③ let percentage = offset / tableView.bounds.height
上記のコードで、やりたいことを図示すると次のようなイメージになります。
各セルは、スクロールすると、テーブルビュー上で上下を移動するわけですが、移動のたびに、このオフセットを取得し、テーブルビュー全体のサイズで割ることで、どの位置に存在しているかを表しています。
そして、この数値は、この後、画像をずらすために使用します。
(4) セルのオフセットに応じて枠ビュー上の画像ビューのオフセットを変化させる
画像ビューをづらす作業は、frameのorigin.yを変化させるだけです。
全部で0〜-100まで、ずらすので、先程取得した0〜1.0を -100 倍して、そのまま使用しています。
let percentage = offset / tableView.bounds.height // ImageViewのframeを遷移させる var imageRect = cell.photoView.frame imageRect.origin.y = percentage * 100 * -1 cell.photoView.frame = imageRect
3 最後に
変化量は、極めて適当に実装してしまいましたが、簡単な実装で、非常に表現力を上げる手法だと思いました。
コードは下記に置きました。気になるところが有りましたら、ぜひ教えてやってください。
[GitHub] https://github.com/furuya02/ParallaxSample