"賢い" ツールチップ
訪問者がマウスを そこを通る のではなく その上 に移動させた場合、その上にツールチップを表示する関数を書いてください。
言い換えると、もし訪問者が要素上にマウス動かして止めた場合 – ツールチップを表示します。そして、もし単にマウスをすばやく移動させた場合にはそれは必要ありません。誰が余分な点滅を必要とするでしょうか?
技術的には、要素上のマウス速度を測る事ができます。そしてもし速度が遅い場合、“要素上” にくると想定してツールチップを表示し、速度が早い場合には – 無視します。
そのための汎用的なオブジェクト new HoverIntent(options)
を作ります。options
は次の通りです:
elem
– 追跡する要素ですover
– マウスが要素をゆっくり移動している場合に呼び出す関数ですout
– マウスが要素を離れるときに呼び出す関数です(もしover
が呼ばれたら)
ツールチップに対してこのようなオブジェクトを使用する例です:
// サンプルのツールチップ
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";
// オブジェクトはマウスを追跡し、over/out を呼び出します
new HoverIntent({
elem,
over() {
tooltip.style.left = elem.getBoundingClientRect().left + 'px';
tooltip.style.top = elem.getBoundingClientRect().bottom + 5 + 'px';
document.body.append(tooltip);
},
out() {
tooltip.remove();
}
});
デモ:
マウスをすばやく移動し、“時計” を横切った場合は何も起こりません。ゆっくり、もしくはその上で停止した場合、ツールチップになります。
注意: ツールチップはカーソルが時計のサブ要素の間を移動するときに “点滅” しません、
アルゴリズムはシンプルです:
- 要素上に
onmouseover/out
ハンドラを置きます。また、ここではonmouserenter/leave
を使うこともできますが、汎用性が下がり、移譲を導入すると上手く動作しません。 - マウスカーソルが要素に入ったとき、
mousemove
で速度の計算を開始します。 - もし速度が遅い場合、
over
を実行します。 - その後、要素から出て、
over
が実行された場合にはout
を実行します。
質問: “どうやって速度を測る?”
最初のアイデア: 100ms
毎に関数を実行し、前後の座標間の距離を計算する方法です。もしそれが小さい場合、スピードは小さいです。
残念ながら、JavaScript で “現在のマウス座標” を取得する方法はありません。getCurrentMouseCoordinates()
のような関数はありません。
座標を取得する唯一の方法は、mousemove
のようにマウスイベントをリッスンすることです。
したがって、座標を追跡しそれを覚えるために mousermove
のハンドラを設定できます。
P.S. 注意: 解決策のテストでは、dispatchEvent
を使用して、ツールチップが正しく動作するかを確認します。