少し変わったやり方で、スワイプで閉じれるHTML要素を実装してみました
僕はもともとasbplayerをスマホ用に作りませんでしたが、今となっては大分使えるようになってきました。スマホでの使用を可能にするためには、asbplayerの機能をアクセスできるオーバーレイを実装し、それを動画要素の上に乗せました。ただし、オーバーレイが動画プレイヤーのUIと被ったり、単に邪魔だったりする可能性があるため、スマホの画面の狭さへの配慮が重要で、オーバーレイを簡単に閉じれるようにしたほうが良いかと考えました。
最初は、閉じるための「X」ボタンをオーバーレイに加えました:
とりあえずの解決方法としては良かったですが、もっとボタンをオーバーレイに詰めようと思ったとき、オーバーレイの領域をなるべく効率的に使う必要がでてきました。それで、ボタンではなく、スワイプで閉じれるようにすれば良いのではないか、という解決方法に至りました。オーバーレイの領域の一部が空くのだけではなく、普通のスマホユーザーにとって、「スワイプで閉じる」という操作には馴染みがあるでしょう。
たまたまそのとき、scroll snapというCSSプロパティーのことを知ったばかりでした。「スワイプで閉じる」という操作は、「スクロールして視野から飛ばす」のと同じようなものだと考えると、もしかしたらこのCSSプロパティーを使えるのではないかと思いました。他の方法を調べようともせず、早速やってみることに取り組みました。
オーバーレイを上にスコールできるようにするためには、オーバーレイの下に何かを置く必要があります。この要素を「スクロールバッファー」だと呼びます。オーバーレイはすでにiframe
の中に入っているので、実装の段取りは次の通りになります。
iframe
の中で、スクロールバッファーの要素をオーバーレイの要素の下に置きます。- この二つの要素とも、スナップスクロール可能な子要素にするために、
scroll-snap-align
のプロパティーを付けます。 iframe
のbody
にsnap-scroll-type
のプロパティーを付け、以上の子要素の親要素にします。- スクロールバーをscrollbar-widthのCSSプロパティーで隠します。
- scrollendのイベントにサブスクライブし、
iframe
がスクロールの最終点に着いたタイミングに反応し、タッチのインプットが下の要素に届くようにiframe
をDOMから外します。
数時間で、91行のコードによってちゃんと動くようになりました:
スクロールバッファを赤にすると、以下の通りになります:
グーグルでこの問題を調べてみると、タッチのイベントでスワイプのジェスチャーを探知し、CSSで要素を画面から飛ばしたりといったような、主にJSを使った解決方法がでてきます。asbplayerで多く使われているMUIも、Swipeable Drawer
というコンポーネントがあります。一見、ぴったりのソリューションには見えますが、CSS寄りの方法を使うことでSwipeable Drawer
のコードの2KBをasbplayerのビルドに加えないで済んだらしいです。さらに、snap-scroll
のCSSのほうが、ブラウザのレンダリングエンジンによって動かされていて、JSがほとんど間に入らないため、すらすらと動きます。