diff --git a/htdocs/lib/FrequencyDisplay.js b/htdocs/lib/FrequencyDisplay.js index 7aeecc74..b6eb1964 100644 --- a/htdocs/lib/FrequencyDisplay.js +++ b/htdocs/lib/FrequencyDisplay.js @@ -98,13 +98,7 @@ TuneableFrequencyDisplay.prototype.setupEvents = function() { if (index < 0) return; var delta = 10 ** (Math.floor(Math.max(me.exponent, Math.log10(me.frequency))) - index); - var newFrequency; - if ('deltaMode' in e.originalEvent && e.originalEvent.deltaMode === 0) { - newFrequency = me.frequency - delta * (e.originalEvent.deltaY / 50); - } else { - if (e.originalEvent.deltaY > 0) delta *= -1; - newFrequency = me.frequency + delta; - } + var newFrequency = me.frequency - delta * wheelDelta(e.originalEvent); me.element.trigger('frequencychange', newFrequency); }); diff --git a/htdocs/lib/wheelDelta.js b/htdocs/lib/wheelDelta.js new file mode 100644 index 00000000..1dbe2549 --- /dev/null +++ b/htdocs/lib/wheelDelta.js @@ -0,0 +1,21 @@ +/* + * Normalize scroll wheel events. + * + * It seems like there's no consent as to how mouse wheel events are presented in the javascript API. The standard + * states that a MouseEvent has a deltaY property that contains the scroll distances, together with a deltaMode + * property that state the "unit" that deltaY has been measured in. The deltaMode can be either pixels, lines or + * pages. The latter is seldomly used in practise. + * + * The troublesome part is that there is no standard on how to correlate the two at this point. + * + * The basic idea is that one tick of a mouse wheel results in a total return value of +/- 1 from this method. + * It's important to keep in mind that one tick of a wheel may result in multiple events in the browser. The aim + * of this method is to scale the sum of deltaY over + */ +function wheelDelta(evt) { + if ('deltaMode' in evt && evt.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { + // chrome and webkit-based browsers seem to correlate one tick of the wheel to 120 pixels. + return evt.deltaY / 120; + } + return evt.deltaY; +} diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index a12e1d85..da229118 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -619,11 +619,7 @@ function get_relative_x(evt) { function canvas_mousewheel(evt) { if (!waterfall_setup_done) return; - var delta = -evt.deltaY; - // deltaMode 0 means pixels instead of lines - if ('deltaMode' in evt && evt.deltaMode === 0) { - delta /= 50; - } + var delta = -wheelDelta(evt); var relativeX = get_relative_x(evt); zoom_step(delta, relativeX, zoom_center_where_calc(evt.pageX)); evt.preventDefault(); @@ -1258,11 +1254,14 @@ function initSliders() { var $slider = $(this); if (!$slider.attr('step')) return; var val = Number($slider.val()); + // restore previous high-resolution mouse wheel delta + var mouseDelta = Number($slider.data('mouseDelta')); + if (mouseDelta) val += mouseDelta; var step = Number($slider.attr('step')); - if (ev.originalEvent.deltaY > 0) { - step *= -1; - } - $slider.val(val + step); + var newVal = val + step * -wheelDelta(ev.originalEvent); + $slider.val(newVal); + // the calculated value can have a higher resolution than the element can store, so we put the delta into the data attributes + $slider.data('mouseDelta', newVal - $slider.val()); $slider.trigger('change'); }); diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py index 2ae1ab14..d9a273fa 100644 --- a/owrx/controllers/assets.py +++ b/owrx/controllers/assets.py @@ -119,6 +119,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController): profiles = { "receiver.js": [ "lib/chroma.min.js", + "lib/wheelDelta.js", "openwebrx.js", "lib/jquery-3.2.1.min.js", "lib/jquery.nanoscroller.min.js",