レッスンに戻る

"賢い" ツールチップ

重要性: 5

訪問者がマウスを そこを通る のではなく その上 に移動させた場合、その上にツールチップを表示する関数を書いてください。

言い換えると、もし訪問者が要素上にマウス動かして止めた場合 – ツールチップを表示します。そして、もし単にマウスをすばやく移動させた場合にはそれは必要ありません。誰が余分な点滅を必要とするでしょうか?

技術的には、要素上のマウス速度を測る事ができます。そしてもし速度が遅い場合、“要素上” にくると想定してツールチップを表示し、速度が早い場合には – 無視します。

そのための汎用的なオブジェクト 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();
  }
});

デモ:

マウスをすばやく移動し、“時計” を横切った場合は何も起こりません。ゆっくり、もしくはその上で停止した場合、ツールチップになります。

注意: ツールチップはカーソルが時計のサブ要素の間を移動するときに “点滅” しません、

テストと一緒にサンドボックスを開く

アルゴリズムはシンプルです:

  1. 要素上に onmouseover/out ハンドラを置きます。また、ここでは onmouserenter/leave を使うこともできますが、汎用性が下がり、移譲を導入すると上手く動作しません。
  2. マウスカーソルが要素に入ったとき、mousemove で速度の計算を開始します。
  3. もし速度が遅い場合、over を実行します。
  4. その後、要素から出て、over が実行された場合には out を実行します。

質問: “どうやって速度を測る?”

最初のアイデア: 100ms 毎に関数を実行し、前後の座標間の距離を計算する方法です。もしそれが小さい場合、スピードは小さいです。

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

座標を取得する唯一の方法は、mousemove のようにマウスイベントをリッスンすることです。

したがって、座標を追跡しそれを覚えるために mousermove のハンドラを設定できます。

P.S. 注意: 解決策のテストでは、dispatchEvent を使用して、ツールチップが正しく動作するかを確認します。

サンドボックスでテストと一緒に解答を開く