レッスンに戻る

「スマート」ツールチップ

重要度:5

訪問者がマウスをその上に移動させた場合にのみ、要素の上にツールチップを表示する関数を作成してください。通過した場合は表示しません。

言い換えれば、訪問者が要素の上にマウスを移動させてそこに留まると、ツールチップを表示します。もしマウスが通過しただけなら、余計な点滅は不要なので表示する必要はありません。

技術的には、要素上でのマウスの速度を測定し、速度が遅ければ「要素の上に来た」とみなし、ツールチップを表示します。速度が速ければ無視します。

それのための汎用オブジェクト new HoverIntent(options) を作成します。

その options

  • elem – トラックする要素。
  • over – マウスが要素に到達した場合に呼び出す関数。つまり、ゆっくり移動するか、要素の上に停止した場合です。
  • out – マウスが要素から離れたときに呼び出す関数(overが呼び出された場合)。

ツールチップにそのようなオブジェクトを使用する例

// a sample tooltip
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";

// the object will track mouse and call 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();
  }
});

デモ

マウスを「時計」の上に速く移動させても何も起こりません。ゆっくりと移動させるか、その上で停止させると、ツールチップが表示されます。

注意: カーソルが時計のサブ要素間を移動しても、ツールチップは「点滅」しません。

テスト付きのサンドボックスを開きます。

アルゴリズムは単純に見えます

  1. 要素に onmouseover/out ハンドラーを配置します。ここでも onmouseenter/leave を使用できますが、これらは汎用性が低く、デリゲーションを導入すると機能しません。
  2. マウスカーソルが要素に入ったら、mousemove で速度の測定を開始します。
  3. 速度が遅い場合は、over を実行します。
  4. 要素から出ていて、over が実行された場合は、out を実行します。

しかし、速度をどのように測定するのでしょうか?

最初のアイデアは、100ms ごとに関数を実行し、前の座標と新しい座標間の距離を測定することです。それが小さい場合、速度は小さいということになります。

残念ながら、JavaScriptで「現在のマウス座標」を取得する方法はありません。 getCurrentMouseCoordinates() のような関数はありません。

座標を取得する唯一の方法は、mousemove のようなマウスイベントをリッスンし、イベントオブジェクトから座標を取得することです。

したがって、mousemove にハンドラーを設定して座標を追跡し、それらを記憶しましょう。そして、100ms ごとに比較します。

追記:解決策のテストでは、ツールチップが正しく機能するかどうかを確認するために dispatchEvent を使用しています。

テスト付きのサンドボックスで解決策を開きます。