Normalizowanie szybkości kółka myszy w różnych przeglądarkach

147

Dla innego pytania ułożyłem tę odpowiedź , w tym ten przykładowy kod .

W tym kodzie używam kółka myszy do powiększania / zmniejszania płótna HTML5. Znalazłem kod, który normalizuje różnice szybkości między przeglądarką Chrome i Firefox. Jednak obsługa zoomu w Safari jest znacznie, znacznie szybsza niż w którymkolwiek z nich.

Oto kod, który obecnie mam:

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

Jakiego kodu mogę użyć, aby uzyskać tę samą wartość „delta” dla tej samej ilości ruchu kółka myszy w przeglądarkach Chrome 10/11, Firefox 4, Safari 5, Opera 11 i IE9?

To pytanie jest powiązane, ale nie ma dobrej odpowiedzi.

Edytować : dalsze badanie pokazuje, że jedno zdarzenie przewijania „w górę” to:

                  | evt.wheelDelta | evt.detail
------------------ + ---------------- + ------------
  Safari v5 / Win7 | 120 | 0
  Safari v5 / OS X | 120 | 0
  Safari v7 / OS X | 12 | 0
 Chrome v11 / Win7 | 120 | 0
 Chrome v37 / Win7 | 120 | 0
 Chrome v11 / OS X | 3 (!) | 0 (prawdopodobnie źle)
 Chrome v37 / OS X | 120 | 0
        IE9 / Win7 | 120 | nieokreślony
  Opera v11 / OS X | 40 | -1
  Opera v24 / OS X | 120 | 0
  Opera v11 / Win7 | 120 | -3
 Firefox v4 / Win7 | niezdefiniowany | -3
 Firefox v4 / OS X | niezdefiniowany | -1
Firefox v30 / OS X | niezdefiniowany | -1

Co więcej, używanie gładzika MacBooka w systemie OS X daje różne rezultaty, nawet przy powolnym ruchu:

  • W Safari i Chrome wheelDeltajest to wartość 3 zamiast 120 dla kółka myszy.
  • W przeglądarce Firefox detailjest to zwykle 2, czasami 1, ale przy bardzo powolnym przewijaniu ŻADNY WYDARZENIE NIE POWODUJE .

Więc pytanie brzmi:

Jaki jest najlepszy sposób na rozróżnienie tego zachowania (najlepiej bez żadnego klienta użytkownika lub podsłuchiwania systemu operacyjnego)?

Phrogz
źródło
Przepraszam, usunąłem moje pytanie. Właśnie piszę odpowiedź. Zanim przejdę dalej, czy mówisz o przewijaniu w Safari w systemie Mac OS X? Kiedy przewijasz trochę, przewija się trochę, ale jeśli utrzymujesz stałą szybkość, stopniowo staje się szybsza?
Blender
@Blender Testuję teraz na OS X i tak, Safari jest odstającym, który powiększa się około 20x szybciej niż Chrome. Niestety nie mam podłączonej fizycznej myszy, więc moje testy ograniczają się do przesunięć dwoma palcami w równych odległościach i prędkościach.
Phrogz
Zaktualizowałem pytanie o szczegóły dotyczące zachowania 5 najpopularniejszych przeglądarek w systemach OS X i Win7. To pole minowe, w którym Chrome na OS X wydaje się być problematyczną wartością odstającą.
Phrogz
@Phrogz Nie powinno tak być e.wheelDelta/120?
Šime Vidas
@ ŠimeVidas Tak, kod, który skopiowałem i którego używałem, był wyraźnie nieprawidłowy. Możesz zobaczyć lepszy kod w mojej odpowiedzi poniżej .
Phrogz

Odpowiedzi:

57

Edytuj wrzesień 2014

Jeśli się uwzględni:

  • Różne wersje tej samej przeglądarki na OS X dawały różne wartości w przeszłości i mogą to robić w przyszłości, i to
  • Używanie gładzika w OS X daje bardzo podobne efekty do używania kółka myszy, ale daje bardzo różne wartości zdarzeń , a mimo to różnica urządzeń nie może zostać wykryta przez JS

… Mogę tylko polecić użycie tego prostego kodu zliczającego znaki:

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

Oryginalna próba bycia poprawną następuje.

Oto moja pierwsza próba skryptu normalizacji wartości. Ma dwie wady w systemie OS X: Firefox na OS X wygeneruje wartości 1/3 takie, jakie powinny być, a Chrome na OS X wygeneruje wartości 1/40 takie, jakie powinny być.

// 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
};

Możesz przetestować ten kod we własnej przeglądarce tutaj: http://phrogz.net/JS/wheeldelta.html

Mile widziane są sugestie dotyczące wykrywania i ulepszania zachowania w przeglądarkach Firefox i Chrome w systemie OS X.

Edycja : jedną sugestią od @Tom jest po prostu policzenie każdego wywołania zdarzenia jako pojedynczego ruchu, używając znaku odległości, aby go dostosować. Nie da to świetnych rezultatów przy płynnym / przyspieszonym przewijaniu w systemie OS X, ani też nie poradzi sobie doskonale w przypadkach, gdy kółko myszy porusza się bardzo szybko (np. wheelDelta240), ale zdarza się to rzadko. Ten kod jest teraz zalecaną techniką pokazaną na początku tej odpowiedzi, z powodów tam opisanych.

Phrogz
źródło
@ ŠimeVidas Dzięki, to w zasadzie to, co mam, poza tym, że uwzględniam również różnicę 1/3 w Operze OS X.
Phrogz
@Phrogz, czy masz zaktualizowaną wersję we wrześniu 2014 roku z dodanymi wszystkimi OS X / 3? To byłby wspaniały dodatek dla społeczności!
Basj
@Phrogz, byłoby wspaniale. Nie mam tu Maca do przetestowania ... (Byłbym szczęśliwy,
mogąc
1
W przeglądarce Firefox 35.0.1 wheelDelta jest niezdefiniowana, a szczegół jest zawsze równy 0, co powoduje, że dostarczony kod nie działa.
Max Strater
1
@MaxStrater W obliczu tego samego problemu dodałem „deltaY”, aby rozwiązać ten problem w takim kierunku, ale (((evt.deltaY <0 || evt.wheelDelta>0) || evt.deltaY < 0) ? 1 : -1)nie jestem pewien, czego dowiaduje się z tego kontrola jakości.
Brock
28

Oto moja szalona próba stworzenia spójnej i znormalizowanej delty między przeglądarkami (-1 <= delta <= 1):

var o = e.originalEvent,
    d = o.detail, w = o.wheelDelta,
    n = 225, n1 = n-1;

// Normalize delta
d = d ? w && (f = w/d) ? d/f : -d/1.35 : w/120;
// Quadratic scale if |d| > 1
d = d < 1 ? d < -1 ? (-Math.pow(d, 2) - n1) / n : d : (Math.pow(d, 2) + n1) / n;
// Delta *should* not be greater than 2...
e.delta = Math.min(Math.max(d / 2, -1), 1);

Jest to całkowicie empiryczne, ale działa całkiem dobrze w Safari 6, FF 16, Opera 12 (OS X) i IE 7 w XP

smrtl
źródło
3
Gdybym mógł zagłosować za jeszcze 10 razy, mógłbym. Dziękuję bardzo!
justnorris
Czy możesz mieć pełny kod funkcjonalny w wersji demonstracyjnej (np. JsFiddle)?
adardesign
Czy istnieje powód, aby buforować się event-przedmiot w o?
yckart
Nie, nie ma. oZmienna jest tam, aby pokazać chcemy oryginalnego zdarzenia, a nie zawinięte wydarzenie jak jQuery lub inne biblioteki mogą przechodzić do obsługi zdarzeń.
smrtl
@smrtl czy mógłbyś wyjaśnić n i n1? Do czego służą te zmienne?
Om3ga,
28

Nasi znajomi z Facebooka opracowali świetne rozwiązanie tego problemu.

Przetestowałem na tabeli danych, którą buduję za pomocą React i przewija się jak masło!

To rozwiązanie działa w różnych przeglądarkach, w systemach Windows / Mac i w obu przy użyciu gładzika / myszy.

// Reasonable defaults
var PIXEL_STEP  = 10;
var LINE_HEIGHT = 40;
var PAGE_HEIGHT = 800;

function normalizeWheel(/*object*/ event) /*object*/ {
  var sX = 0, sY = 0,       // spinX, spinY
      pX = 0, pY = 0;       // pixelX, pixelY

  // Legacy
  if ('detail'      in event) { sY = event.detail; }
  if ('wheelDelta'  in event) { sY = -event.wheelDelta / 120; }
  if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; }
  if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; }

  // side scrolling on FF with DOMMouseScroll
  if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
    sX = sY;
    sY = 0;
  }

  pX = sX * PIXEL_STEP;
  pY = sY * PIXEL_STEP;

  if ('deltaY' in event) { pY = event.deltaY; }
  if ('deltaX' in event) { pX = event.deltaX; }

  if ((pX || pY) && event.deltaMode) {
    if (event.deltaMode == 1) {          // delta in LINE units
      pX *= LINE_HEIGHT;
      pY *= LINE_HEIGHT;
    } else {                             // delta in PAGE units
      pX *= PAGE_HEIGHT;
      pY *= PAGE_HEIGHT;
    }
  }

  // Fall-back if spin cannot be determined
  if (pX && !sX) { sX = (pX < 1) ? -1 : 1; }
  if (pY && !sY) { sY = (pY < 1) ? -1 : 1; }

  return { spinX  : sX,
           spinY  : sY,
           pixelX : pX,
           pixelY : pY };
}

Kod źródłowy można znaleźć tutaj: https://github.com/facebook/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js

Jerzy
źródło
3
Bardziej bezpośredni link, który nie został dołączony do oryginalnego kodu normalizeWHeel.js github.com/facebook/fixed-data-table/blob/master/src/…
Robin Luiten
Dzięki @RobinLuiten, aktualizuję oryginalny post.
George
Ten materiał jest genialny. Właśnie to wykorzystałem i działa jak urok! Dobra robota Facebook :)
perry
Czy możesz podać przykład, jak go używać? Próbowałem i działa w FF ale nie w Chrome czy IE (11) ..? Dzięki
Andrew
2
Dla każdego, kto używa npm, jest gotowy do użycia pakiet zawierający tylko ten kod już wyodrębniony ze Stałej Tabeli Danych Facebooka. Zobacz tutaj, aby uzyskać więcej informacji npmjs.com/package/normalize-wheel
Simon Watson
11

Zrobiłem tabelę z różnymi wartościami zwracanymi przez różne zdarzenia / przeglądarki, biorąc pod uwagę DOM3 wheel zdarzenie , które niektóre przeglądarki już obsługują (tabela poniżej).

Na tej podstawie wykonałem tę funkcję, aby znormalizować prędkość:

http://jsfiddle.net/mfe8J/1/

function normalizeWheelSpeed(event) {
    var normalized;
    if (event.wheelDelta) {
        normalized = (event.wheelDelta % 120 - 0) == -0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
    } else {
        var rawAmmount = event.deltaY ? event.deltaY : event.detail;
        normalized = -(rawAmmount % 3 ? rawAmmount * 10 : rawAmmount / 3);
    }
    return normalized;
}

Stół dla mousewheel, wheeli DOMMouseScrollzdarzeń:

| mousewheel        | Chrome (win) | Chrome (mac) | Firefox (win) | Firefox (mac) | Safari 7 (mac) | Opera 22 (mac) | Opera 22 (win) | IE11      | IE 9 & 10   | IE 7 & 8  |
|-------------------|--------------|--------------|---------------|---------------|----------------|----------------|----------------|-----------|-------------|-----------|
| event.detail      | 0            | 0            | -             | -             | 0              | 0              | 0              | 0         | 0           | undefined |
| event.wheelDelta  | 120          | 120          | -             | -             | 12             | 120            | 120            | 120       | 120         | 120       |
| event.wheelDeltaY | 120          | 120          | -             | -             | 12             | 120            | 120            | undefined | undefined   | undefined |
| event.wheelDeltaX | 0            | 0            | -             | -             | 0              | 0              | 0              | undefined | undefined   | undefined |
| event.delta       | undefined    | undefined    | -             | -             | undefined      | undefined      | undefined      | undefined | undefined   | undefined |
| event.deltaY      | -100         | -4           | -             | -             | undefined      | -4             | -100           | undefined | undefined   | undefined |
| event.deltaX      | 0            | 0            | -             | -             | undefined      | 0              | 0              | undefined | undefined   | undefined |
|                   |              |              |               |               |                |                |                |           |             |           |
| wheel             | Chrome (win) | Chrome (mac) | Firefox (win) | Firefox (mac) | Safari 7 (mac) | Opera 22 (mac) | Opera 22 (win) | IE11      | IE 10 & 9   | IE 7 & 8  |
| event.detail      | 0            | 0            | 0             | 0             | -              | 0              | 0              | 0         | 0           | -         |
| event.wheelDelta  | 120          | 120          | undefined     | undefined     | -              | 120            | 120            | undefined | undefined   | -         |
| event.wheelDeltaY | 120          | 120          | undefined     | undefined     | -              | 120            | 120            | undefined | undefined   | -         |
| event.wheelDeltaX | 0            | 0            | undefined     | undefined     | -              | 0              | 0              | undefined | undefined   | -         |
| event.delta       | undefined    | undefined    | undefined     | undefined     | -              | undefined      | undefined      | undefined | undefined   | -         |
| event.deltaY      | -100         | -4           | -3            | -0,1          | -              | -4             | -100           | -99,56    | -68,4 | -53 | -         |
| event.deltaX      | 0            | 0            | 0             | 0             | -              | 0              | 0              | 0         | 0           | -         |
|                   |              |              |               |               |                |                |                |           |             |           |
|                   |              |              |               |               |                |                |                |           |             |           |
| DOMMouseScroll    |              |              | Firefox (win) | Firefox (mac) |                |                |                |           |             |           |
| event.detail      |              |              | -3            | -1            |                |                |                |           |             |           |
| event.wheelDelta  |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.wheelDeltaY |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.wheelDeltaX |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.delta       |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.deltaY      |              |              | undefined     | undefined     |                |                |                |           |             |           |
| event.deltaX      |              |              | undefined     | undefined     |                |                |                |           |             |           |
Sergio
źródło
2
Skutkuje różnymi prędkościami przewijania w aktualnych przeglądarkach Safari i Firefox pod macOS.
Lenar Hoyt
6

Kolejne, mniej lub bardziej samodzielne rozwiązanie ...

Nie wymaga to jednak uwzględnienia czasu między wydarzeniami. Niektóre przeglądarki wydają się zawsze uruchamiać zdarzenia z tą samą różnicą i po prostu uruchamiają je szybciej podczas szybkiego przewijania. Inni zmieniają delty. Można sobie wyobrazić adaptacyjny normalizator, który bierze pod uwagę czas, ale byłby nieco skomplikowany i niezręczny w użyciu.

Praca dostępna tutaj: jsbin / iqafek / 2

var normalizeWheelDelta = function() {
  // Keep a distribution of observed values, and scale by the
  // 33rd percentile.
  var distribution = [], done = null, scale = 30;
  return function(n) {
    // Zeroes don't count.
    if (n == 0) return n;
    // After 500 samples, we stop sampling and keep current factor.
    if (done != null) return n * done;
    var abs = Math.abs(n);
    // Insert value (sorted in ascending order).
    outer: do { // Just used for break goto
      for (var i = 0; i < distribution.length; ++i) {
        if (abs <= distribution[i]) {
          distribution.splice(i, 0, abs);
          break outer;
        }
      }
      distribution.push(abs);
    } while (false);
    // Factor is scale divided by 33rd percentile.
    var factor = scale / distribution[Math.floor(distribution.length / 3)];
    if (distribution.length == 500) done = factor;
    return n * factor;
  };
}();

// Usual boilerplate scroll-wheel incompatibility plaster.

var div = document.getElementById("thing");
div.addEventListener("DOMMouseScroll", grabScroll, false);
div.addEventListener("mousewheel", grabScroll, false);

function grabScroll(e) {
  var dx = -(e.wheelDeltaX || 0), dy = -(e.wheelDeltaY || e.wheelDelta || 0);
  if (e.detail != null) {
    if (e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
    else if (e.axis == e.VERTICAL_AXIS) dy = e.detail;
  }
  if (dx) {
    var ndx = Math.round(normalizeWheelDelta(dx));
    if (!ndx) ndx = dx > 0 ? 1 : -1;
    div.scrollLeft += ndx;
  }
  if (dy) {
    var ndy = Math.round(normalizeWheelDelta(dy));
    if (!ndy) ndy = dy > 0 ? 1 : -1;
    div.scrollTop += ndy;
  }
  if (dx || dy) { e.preventDefault(); e.stopPropagation(); }
}
Marijn
źródło
1
To rozwiązanie w ogóle nie działa z Chrome na Macu z gładzikiem.
justnorris
@Norris Wierzę, że teraz tak. Właśnie znalazłem to pytanie, a przykład tutaj działa na moim Macbooku z Chrome
Harry Moreno
4

Proste i działające rozwiązanie:

private normalizeDelta(wheelEvent: WheelEvent):number {
    var delta = 0;
    var wheelDelta = wheelEvent.wheelDelta;
    var deltaY = wheelEvent.deltaY;
    // CHROME WIN/MAC | SAFARI 7 MAC | OPERA WIN/MAC | EDGE
    if (wheelDelta) {
        delta = -wheelDelta / 120; 
    }
    // FIREFOX WIN / MAC | IE
    if(deltaY) {
        deltaY > 0 ? delta = 1 : delta = -1;
    }
    return delta;
}
Marek
źródło
3

Aby korzystać z funkcji zoom na urządzeniach dotykowych, zarejestruj się w przypadku zdarzeń Geststart, Gestchange i Gestendend i użyj właściwości event.scale. Możesz zobaczyć przykładowy kod .

W przypadku przeglądarki Firefox 17 onwheelwydarzenie ma być obsługiwane przez wersje stacjonarne i mobilne (zgodnie z dokumentacją MDN na onwheel ). Również dla Firefoksa może być MozMousePixelScrollprzydatne zdarzenie specyficzne dla Gecko (chociaż przypuszczalnie jest to teraz przestarzałe, ponieważ zdarzenie DOMMouseWheel jest teraz przestarzałe w Firefoksie).

W systemie Windows wydaje się, że sam sterownik generuje zdarzenia WM_MOUSEWHEEL, WM_MOUSEHWHEEL (i może zdarzenie WM_GESTURE do przesuwania panelu dotykowego?). To wyjaśniałoby, dlaczego Windows lub przeglądarka nie wydają się normalizować samych wartości zdarzeń kółka myszy (i może oznaczać, że nie można napisać niezawodnego kodu w celu znormalizowania wartości).

Do obsługi zdarzeń onwheel( nie onmousewheel) w programie Internet Explorer dla IE9 i IE10 można również użyć standardowego onwheel zdarzenia W3C . Jednak jedno wycięcie może być wartością inną niż 120 (np. Pojedyncze wycięcie staje się 111 (zamiast -120) na mojej myszy przy użyciu tej strony testowej ). Napisałem kolejny artykuł z innymi szczegółami wydarzeń na kole, które mogą być istotne.

Zasadniczo w moich własnych testach zdarzeń kółka (próbuję znormalizować wartości przewijania) stwierdziłem, że otrzymuję różne wartości dla systemu operacyjnego, producenta przeglądarki, wersji przeglądarki, typu zdarzenia i urządzenia (mysz Microsoft tiltwheel, gesty touchpada laptopa , touchpad laptopa z funkcją scrollzone, mysz Apple Magic Mouse, kulka przewijania myszy Apple Mighty Mouse, touchpad Mac itp.).

I trzeba zignorować różne efekty uboczne z konfiguracji przeglądarki (np. Firefox mousewheel.enable_pixel_scrolling, chrome --scroll-pixels = 150), ustawienia sterownika (np. Touchpad Synaptics) i konfiguracji systemu operacyjnego (ustawienia myszy Windows, preferencje myszy OSX, Ustawienia przycisku X.org).

robocat
źródło
2

To problem, z którym walczę od kilku godzin i to nie pierwszy raz :(

Próbowałem podsumować wartości za pomocą „machnięcia” i zobaczyć, jak różne przeglądarki zgłaszają wartości, i bardzo się one różnią, przy czym Safari zgłasza o rząd wielkości większe liczby na prawie wszystkich platformach, Chrome raportuje znacznie więcej (np. 3 razy więcej ) niż firefox, firefox jest zrównoważony na dłuższą metę, ale różni się między platformami na małych ruchach (na Ubuntu gnome, prawie tylko +3 lub -3, wygląda na to, że podsumowuje mniejsze zdarzenia, a następnie wysyła duże „+3”)

Obecnie znalezione rozwiązania to trzy:

  1. Wspomniane już „używaj tylko znaku” zabijające wszelkie przyspieszenia
  2. Sniff przeglądarkę do pomniejszej wersji i platformy i odpowiednio dostosuj
  3. Qooxdoo niedawno zaimplementowało algorytm samodostosowujący się, który zasadniczo próbuje skalować deltę na podstawie dotychczas otrzymanych wartości minimalnej i maksymalnej.

Pomysł w Qooxdoo jest dobry i działa, i jest jedynym rozwiązaniem, które obecnie uważam za całkowicie spójne dla różnych przeglądarek.

Niestety ma tendencję do renormalizowania również przyspieszenia. Jeśli spróbujesz tego (w ich demach) i przewiniesz przez chwilę w górę iw dół z maksymalną prędkością, zauważysz, że przewijanie ekstremalnie szybkie lub bardzo wolne generuje prawie taką samą ilość ruchu. Z drugiej strony, jeśli ponownie załadujesz stronę i będziesz ją przesuwać bardzo powoli, zauważysz, że przewija się ona dość szybko ”.

Jest to frustrujące dla użytkownika Maca (takiego jak ja), który energicznie przesuwał po touchpadzie i spodziewając się, że dostanie się na górę lub dół przewijanej rzeczy.

Co więcej, ponieważ skaluje prędkość myszy w oparciu o maksymalną uzyskaną wartość, im bardziej użytkownik próbuje ją przyspieszyć, tym bardziej będzie spowalniać, podczas gdy użytkownik „powolnego przewijania” doświadczy dość dużej szybkości.

To sprawia, że ​​to (skądinąd genialne) rozwiązanie jest nieco lepszą implementacją rozwiązania 1.

Przeportowałem rozwiązanie do wtyczki jquery mousewheel: http://jsfiddle.net/SimoneGianni/pXzVv/

Jeśli będziesz się nim bawić przez chwilę, zobaczysz, że zaczniesz uzyskiwać dość jednorodne wyniki, ale zauważysz również, że dość szybko osiąga on wartości + 1 / -1.

Pracuję teraz nad ulepszeniem go, aby lepiej wykrywał piki, tak aby nie wysyłały wszystkiego „poza skalę”. Byłoby również dobrze otrzymać wartość zmiennoprzecinkową z zakresu od 0 do 1 jako wartość delty, tak aby uzyskać spójne wyjście.

Simone Gianni
źródło
1

Zdecydowanie nie ma prostego sposobu na normalizację dla wszystkich użytkowników we wszystkich systemach operacyjnych i we wszystkich przeglądarkach.

Robi się gorzej niż twoje wymienione warianty - na mojej konfiguracji WindowsXP + Firefox3.6 moje kółko myszy wykonuje 6 na przewijanie o jeden stopień - prawdopodobnie dlatego, że gdzieś zapomniałem, że przyspieszyłem kółko myszy, albo w systemie operacyjnym, albo gdzieś w okolicy: config

Jednak pracuję nad podobnym problemem (przy okazji z podobną aplikacją, ale nie na płótnie) i pojawia się on po prostu używając znaku delta +1 / -1 i mierząc czas po ostatnim uruchomieniu, mieć szybkość przyspieszenia, tj. jeśli ktoś przewinie raz vs kilka razy w ciągu kilku chwil (założę się, że tak robią to mapy Google).

Koncepcja wydaje się działać dobrze w moich testach, po prostu dodaj do przyspieszenia mniej niż 100 ms.

ck_
źródło
-2
var onMouseWheel = function(e) {
    e = e.originalEvent;
    var delta = e.wheelDelta>0||e.detail<0?1:-1;
    alert(delta);
}
$("body").bind("mousewheel DOMMouseScroll", onMouseWheel);
Matthieu Chavigny
źródło