本連載は分散型マイクロブログ用オープンソースソフトウェアMisskeyの開発に関する紹介と、関連するWeb技術について解説を行っています。
今回は、予測三角形(prediction cone)を用いて、ネストしたポップアップメニューのUXを向上させる手法を紹介します。
モチベーション
ネストしたポップアップメニューで、子メニューにカーソルを移動しようとして別の子メニューが開いてしまう、という経験はありませんか?
特にメニュー項目が横に長い場合は、カーソルの移動距離も増えるため発生しやすくなります。
一般にこの挙動を防止するために、子メニューが開くまでに少しラグを追加する手法が広く使われていると感じます。
これなら、一瞬だけなら他の親項目にカーソルが触れても反応することはありません。
しかしこの方法では、わずかとはいえラグが発生しますので、それはそれでユーザー体験としてはプチストレスになりえます。
Misskey内に表示されるポップアップメニューにもこの
予測三角形
そんな中、一部のネイティブアプリ等では
文章では分かりにくいので、先に完成したものを以下に示します。
予想した軌跡を視覚化するとこうなっています。
カーソルの移動距離が増える(=子メニューに近づく)ほどブレは大きくなる傾向があるので、予測される軌跡は子メニュー側が底面となる三角形として計算しています。
この三角形は
このシェイプによって、カーソルの動きが下の項目に伝わるのをガードします。
この方法であれば、余分なラグを追加することなく、意図せず触れた項目が反応することを防げます。
実装
このシェイプの描画(といっても実際には不可視。DOMのみに存在)ですが、Web上で実装するにあたってはclip-pathを使う方法を考えました。
clip-pathは、要素を任意の形状にクリッピングできるCSSプロパティです。
ガードとなる要素をメニューの上に重ね、それをclip-pathのpolygon関数で三角形に切り取ります。
polygonでは、任意の多角形の各頂点座標(X/
例えば三角形の先端(A)をカーソル座標にし、底辺(B、C)をそれぞれ子メニューの上側の座標と下側の座標になるようにします。
親項目上でmousemoveイベントを監視することで、三角形の尖端がカーソル座標に追従するようにできます。
実際のMisskeyでの実装は以下になります。興味があれば参照してください。
コツ
三角形の底になる辺の長さは子メニューの高さぴったりではなく、多少拡大させたほうが経験上より安定します。ただ、広げすぎても操作感が悪くなります。
また、必ずしも三角形である必要はなく、例えばラッパ型などより最適な形状があるかもしれません。もちろん単純な三角形より実装は複雑になります。
マウスの動かし方のクセは人それぞれですし、そのあたりの最適解を見つけるのは難しいかもしれません。
注意点として、メニュー内でスクロール可能な場合、スクロール量も考慮する必要があるほか、右側にスペースが無いなどで子メニューが左側に開く可能性がある場合はシェイプの向きの考慮も必要になります。
さらに、タッチ操作時は益がないばかりか操作の邪魔になりますので、マウスでの操作が行われている場合のみ当機能を有効化する必要があります。
あとこれはChromeだけのバグかもしれませんが、シェイプのX座標を100%にして要素の端まで完全に覆ったとしても、なぜか一番端ぎりぎりにカーソルを移動させると後ろの要素に判定が貫通したので、端の座標は101%にする必要がありました。
まとめ
今回はネストしたメニューで操作感を向上させる手法について紹介しました。
ネスト可能なメニューシステムを自前実装することは多くはないと思いますが、知っていて損はないテクニックです。
この予測三角形を利用したUX向上の改修はMisskey v2026.
リリースノートでは
