2019年10月18日

CSSだけでmousemoveイベント実装!?CSSマジックの世界

この記事を読むと理解できること

まずは、以下の作品にマウスで触れて(スマホならタップして)みてください。
マウスの位置に応じて、中央のオブジェクトが回転します。

このインタラクションは マウスイベント含め、すべてCSSだけで実現 しています。
当記事では、この不思議なインターフェイスの仕組みをわかりやすく解説します。


See the Pen Only CSS: 3D Scan by Yusuke Nakaya (@YusukeNakaya) on CodePen.


マウス位置を擬似的に処理する

トリガー

ご存知の通り、CSSだけではマウスの位置を取得することはできません。
しかし、擬似クラス :hover なら、マウスで触れたときの振る舞いを指定できます。

そうであるなら理論上、1pxの要素を画面全体に敷き詰めて :hover を指定すれば マウス位置に反応する空間を作り出すことができる 、と言えます。

ただし、この理論にはパフォーマンスの問題があります(実際にやると危険です)。
現実的には縦20x横20=400要素程度であれば、パフォーマンスを維持して違和感の少ない操作性を実現できます。

便宜上、この :hover 付きの要素を トリガー と呼びます。
以下サンプルで、画面全体にトリガーが敷き詰められている様子が確認できます。
なお、敷き詰める方法には display: grid; を使用しています。


See the Pen DEMO: Magic1 by Yusuke Nakaya (@YusukeNakaya) on CodePen.


兄弟要素の状態を変化させる

ターゲット

一般的に、 :hover はボタン要素の状態変化(色を変える)などに使用されます。

しかし今回は、ここで一工夫。
間接セレクタ ~(チルダ)を用いて 兄弟要素の状態を変化 させます。

以下サンプルで、中央に配置された矩形はトリガーの兄弟要素です。
便宜上、この兄弟要素を ターゲット と呼びます。
トリガーの :hover 指定によって、ターゲットの状態が変化する様子を確認できます。
なお、 ~ を使用する都合上、ターゲットはトリガーよりもうしろに記述する必要があります。


See the Pen DEMO: Magic2 by Yusuke Nakaya (@YusukeNakaya) on CodePen.


トリガーごとに細かく指定する

当然ですが、トリガーはそれぞれ個別に :hover 指定できます。
つまり、トリガーの数だけターゲットの状態を変化させることができます。

以下サンプルでは、 Sassの random() メソッドを用いて transform: translate(); をランダムに変化させています。
触れているトリガーごとに、ターゲットの位置が変わる様子を確認できます。


See the Pen DEMO: Magic3 by Yusuke Nakaya (@YusukeNakaya) on CodePen.


見栄えを整える

ここまで基礎的なロジックを解説してきました。
ここから先は工夫次第。
見栄えを整え、 マジックの世界 に誘います。

ポイントは トリガーのホバー指定を行列で整理して、行番号、列番号に応じてターゲットの変化方法を調整 することです。

以下サンプルでは、トリガーの border を削除して視覚的に隠し、また :hover 指定によってターゲットを3D変化させています。
トリガーを隠すだけで、あたかもマウス位置を取得してアニメーションを実行しているかのような錯覚があります。

サンプルのように 3D変化させるためにはいくつかの工夫が必要 ですので、コードも合わせて確認してください。
たとえば、3D変形のX軸とY軸を別々にコントロールするために、それぞれに対応する要素 .camera を入れ子で追加しています。
また、子要素の3D変形を描画するためには transform-style: preserve-3d; が必要です。


See the Pen DEMO: Magic4 by Yusuke Nakaya (@YusukeNakaya) on CodePen.


この仕組みを利用した作品集

この仕組みを利用している作品をいくつか紹介します。
ロジックはシンプルでなので、さまざまな表現に流用できます。
もちろん、これらの作品はすべて、CSSのみで作られています。

Only CSS: Water Surface

マウスに追従する、水の波紋。
このような2D作品の方が、擬似的なmousemoveイベントを体感しやすいですね。
以前、当ブログで紹介した Liquid CSS のテクニックも応用しています。


See the Pen Only CSS: Water Surface by Yusuke Nakaya (@YusukeNakaya) on CodePen.


Only CSS: Birthday Cake🎂

くるくる回して、眺めるだけのバースデーケーキ。
ケーキをクリックすると、1カットずつ食べられる(減っていく)仕掛けも作りました。
いちごは絵文字を使っているので、環境によっては崩れるかも?


See the Pen Only CSS: Birthday Cake🎂 by Yusuke Nakaya (@YusukeNakaya) on CodePen.


Only CSS: STARFOX Arwing Drone

どこかで見たことあるような、宇宙戦闘機。
画面をクリックすると、戦闘機がバレルロールする仕掛けも作りました。
ドローンのような操作感、浮遊感を意識してアニメーションチューニングしています。


See the Pen Only CSS: STARFOX Arwing Drone by Yusuke Nakaya (@YusukeNakaya) on CodePen.


Only CSS: Responsive City Drone View

鳥の視点で、街の上空を飛んでいるようなコンセプト作品。
遠いビルが霞んで見える、フォグ表現にも挑戦しました。
ややカクカクしますが、建物を避けるゲームのような操作性を意識しています。


See the Pen Only CSS: Responsive City Drone View by Yusuke Nakaya (@YusukeNakaya) on CodePen.


まとめ

種明かし

CSSだけでmousemoveイベントのように振る舞う 基本ロジックは、以下の簡単3ステップ。

  1. トリガー(指定元の要素)を画面全体に敷き詰める
  2. ターゲット(指定先の要素)をトリガーの兄弟要素として配置する
  3. ホバー指定と間接セレクタで、トリガーからターゲットの状態を変化させる(下記の簡単CSSレシピ)

.trigger:hover ~ .target {}

これを作る意味

ここで紹介したテクニックは、はっきり言って まったく実用的ではありません
実務での活用はお控えください。

では、なぜ作るのか。
これは、CSSの可能性を示す実験結果です。
CSSを極めたジョーク作品 としてお楽しみください。

増え続けるジョーク作品集

CodePen
https://codepen.io/YusukeNakaya/
よかったらフォローしてください!

RELATED POSTS