1. ホーム
  2. javascript

[解決済み] ブラウザ間のマウスホイール速度の正規化

2022-04-26 21:11:09

質問

対象 別の質問 を構成しました。 この回答 を含む。 このサンプルコード .

このコードでは、HTML5 Canvas のズームイン/アウトにマウスホイールを使用しています。Chrome と Firefox の速度差を正規化するコードをいくつか見つけました。しかし、Safari のズーム処理は、これらのいずれよりもずっとずっと高速です。

現在、私が持っているコードは以下の通りです。

var handleScroll = function(e){
  var delta = e.wheelDelta ? e.wheelDelta/40 : e.detail ? -e.detail/3 : 0;
  if (delta) ...
  return e.preventDefault() && false;
};
canvas.addEventListener('DOMMouseScroll',handleScroll,false); // For Firefox
canvas.addEventListener('mousewheel',handleScroll,false);     // Everyone else

Chrome v10/11, Firefox v4, Safari v5, Opera v11, IE9で、同じ量のマウスホイール回転で同じ「デルタ」値を得るには、どんなコードを使えばよいでしょうか。

この質問 は関連するが、良い答えがない。

編集 : さらに調査したところ、1つのスクロールイベント「上」は

                  | evt.wheelDelta | evt.detail
------------------+----------------+------------
  サファリ v5/Win7|120|0
  サファリ v5/OS X|120|0
  サファリ v7/OS X|12|0
 クローム v11/Win7|120|0
 クローム v37/Win7|120|0
 Chrome v11/OS X|3(!)|0(間違っている可能性あり)
 クローム v37/OS X|120|0
        IE9/Win7|120|未定義
  オペラ v11/OS X|40|-1
  オペラ v24/OS X|120|0
  オペラv11/Win7|120|-3
 Firefox v4/Win7|未定|-3
 Firefox v4/OS X|未定義|-1
Firefox v30/OS X|未定|-1

さらに、MacBookのトラックパッドをOS Xで使用すると、ゆっくり動いても異なる結果が得られます。

  • SafariとChromeでは wheelDelta は、マウスホイールの値が120ではなく、3になっています。
  • Firefoxでは detail は通常 2 は、時々 1 しかし、非常にゆっくりスクロールした場合 イベントハンドラが全く起動しない .

そこで質問です。

この動作を区別する最善の方法は何でしょうか(ユーザーエージェントやOSのスニッフィングがないのが理想です)。

解決方法は?

2014年9月編集

それを考えると

  • OS X上の同じブラウザの異なるバージョンで過去に異なる値が得られ、また将来もそうなる可能性があり、また
  • OS Xでトラックパッドを使用すると、非常に似た結果が得られます。 効果 はマウスホイールと同じですが、イベント内容は大きく異なります。 そして、そのデバイスの違いをJSで検出することはできません。

...私は、このシンプルで符号ベースのカウントコードを使用することをお勧めします。

var handleScroll = function(evt){
  if (!evt) evt = event;
  var direction = (evt.detail<0 || evt.wheelDelta>0) ? 1 : -1;
  // Use the value as you will
};
someEl.addEventListener('DOMMouseScroll',handleScroll,false); // for Firefox
someEl.addEventListener('mousewheel',    handleScroll,false); // for everyone else


オリジナルの試みは以下の通りです。

ここで、値を正規化するスクリプトに初めて挑戦してみました。OS Xでは2つの欠点があります。OS XのFirefoxは、あるべき値の1/3の値を生成し、OS XのChromeは、あるべき値の1/40の値を生成します。

// Returns +1 for a single wheel roll 'up', -1 for a single roll 'down'
var wheelDistance = function(evt){
  if (!evt) evt = event;
  var w=evt.wheelDelta, d=evt.detail;
  if (d){
    if (w) return w/d/40*d>0?1:-1; // Opera
    else return -d/3;              // Firefox;         TODO: do not /3 for OS X
  } else return w/120;             // IE/Safari/Chrome TODO: /3 for Chrome OS X
};

このコードを自分のブラウザで試すには、こちらをご覧ください。 http://phrogz.net/JS/wheeldelta.html

OS X上のFirefoxとChromeでの検出と動作改善の提案を歓迎します。

編集 : Tom からの提案のひとつは、各イベントの呼び出しを単純にひとつの動きとしてカウントし、距離の符号を使って調整することです。この方法は、OS X のスムーズ/アクセラレーションスクロールでは良い結果を得られませんし、マウスホイールを非常に速く動かした場合 (例. wheelDelta が240の場合)しかし、このようなことはめったにありません。このコードは、そこに書かれている理由から、現在ではこの回答の一番上に示されている推奨テクニックとなっています。