Javascript - MouseWheel
Most modern browsers (except Safari) support the use of the mouse wheel.
I used it to zoom an image.
Unfortunately, the code is not standardized - as of May 2015, it has to be hacked together.
Initial code
This is the code that worked in Chrome.
var canvas = document.getElementById("mapCanvas");
canvas.addEventListener("mousewheel", function(event){ // anonymous function, has no name
var evt = mouseXY(event);
var delta = event.wheelDelta ;
// The -0.5 represents the middle of the map
var current_x = -translatePos.x + (evt.clientX/canvas.width -0.5)*coord.w/scale;
var current_y = -translatePos.y + (evt.clientY/canvas.height-0.5)*coord.h/scale;
if (delta > 0){
scale *= scaleMultiplier;
scale = Math.min(scale,32.0); // changed from 8 to 32 because some stations are very close
} else {
scale /= scaleMultiplier;
scale = Math.max(scale,1.0)
}
translatePos.x = (evt.clientX/canvas.width -0.5)*coord.w/scale - current_x ; // move old position under mouse
translatePos.y = (evt.clientY/canvas.height-0.5)*coord.h/scale - current_y ; // clipping may cause some motion
bound(); // this limits the scroll bounds
drawMap();
});
drawMap();
};
// get mouse coordinates in canvas
function mouseXY( e )
{
var rect = document.getElementById("mapCanvas").getBoundingClientRect();
return { clientX:(e.clientX-rect.left), clientY:(e.clientY-rect.top) }
}
|
However, this code has a basic problem -
when the image is zoomed, the web page also scrolls.
The solution was to add the following
event.preventDefault(); // works with both Chrome and FireFox
|
which tells the browser that my code has found the event useful and that
the browser should simply ignore it.
These, all suggested by various web pages, do not work with Chrome.
return false; // some claim this is for jQuery only
event.stopPropagation(); // does not work with Chrome or FireFox
event.stopImmediatePropagation(); // does not work with Chrome or FireFox
|
Firefox
Well, the code above does not work in Firefox.
From
How to Use the Mouse Wheel Event in HTML5 Pages,
this attaches the event.
var myimage = document.getElementById("myimage");
if (myimage.addEventListener) {
// IE9, Chrome, Safari, Opera
myimage.addEventListener("mousewheel", MouseWheelHandler, false);
// Firefox
myimage.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
// IE 6/7/8
} else
myimage.attachEvent("onmousewheel", MouseWheelHandler);
|
The value indicating how far the wheel moved, and its direction, is also different with FireFox (!@#$%!!!)
- The property name is different
- The returned value is different
- The sign of the value is different
The following code sets delta to either +1 or -1 in all browsers.
function MouseWheelHandler(e) {
// cross-browser wheel delta
var e = window.event || e; // old IE support - I normaly leave this line out
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
|
Notice that this example
discards the event passed via the function parameter
in order to support older browsers .. I normally leave that out.
In a related case, when you want lots of elements calling the same function,
you need special code (yet again) to make it work in FireFox.
// var image = event.srcElement; // everythig except FireFox
var image = event.target || event.srcElement; // includes FireFox
|
These are fragments of the code I used for a project.
var canvas = document.getElementById("mapCanvas");
window.onload = function()
{
// 2 events are required to support both Chrome and FireFox
canvas.addEventListener("mousewheel", function(event){ zoomMap(event); }); // Chrome method
canvas.addEventListener("DOMMouseScroll", function(event){ zoomMap(event); }); // FireFox method
}
zoomMap = function(event) // the actual function is much larger than this
{
var evt = mouseXY(event);
// var delta = event.wheelDelta ; // works in Chrome, will not work in FireFox
var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); // works with both Chrome and FireFox
// stop the browser from scrolling the entire page
event.stopPropagation(); // does not work with Chrome or Firefox
event.stopImmediatePropagation(); // does not work with Chrome or Firefox
event.preventDefault(); // works with both Chrome and FireFox
var x = evt.clientX;
var y = evt.clientY;
}
|
In another program, the following worked in chrome, but not in Firefox 24.0 -
the object event was known in Chrome without being explicitly passed.
mcAlgorithmw.addEventListener("wheel", function(){ mcAlgorithmw_Wheel(); }) ;
mcAlgorithmw_Wheel = function (){ // fails in Firefox 24.0
var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); // works with Chrome
}
|
Firefox 24.0 produces (in debug mode)
The examples above work fine when the mouse wheel does all the work.
However, for edit fields I want to point all the fields to a common event handler
and then have the assocaited onchange event called.
Unfortunately, that is not how javascript works.
I tried to find a way to call (or trigger) the event from the existing handler -
but I never found a way to accomplish that.
Instead, I assign a function to the oninput property and,
if it is assigned, the program calls it.
This also has the side effect (in Chrome at least) that the function is called
as the user types into the field.
To be clear, I never attached an EventListener but just assigned the function
to the property.
(I have no idea if the property stores a pointer (address) to the function or
a copy of the function itself. The documentation is not clear about this.)
mcPressureText.addEventListener("wheel", function() { mcNumber_Wheel() ; }) ; // for Chrome
mcPressureText.addEventListener("DOMMouseScroll", function(event){ mcNumber_Wheel(event); }) ; // for Firefox
mcPressureText.oninput = Temp_pressure_Change;
|
Firefox is a !@##$$ - without a doubt!!
mcTemp_K_UIText.addEventListener("wheel", function(event){ mcNumber_Wheel(event); }) ; // Chrome method
mcTemp_K_UIText.addEventListener("DOMMouseScroll", function(event){ mcNumber_Wheel(event); }) ; // for Firefox
|
This does not cause Firefox to crash - it does not work or cause problems.
mcTemp_K_UIText.addEventListener("wheel", mcNumber_Wheel ) ; // Chrome method
|
However, the following works in Chrome but fails in Firefox.
function mcNumber_Wheel(){
var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); // works with both Chrome and FireFox
var target = event.target;
}
|
To fix it in Firefox, the input parameter must be specified.
function mcNumber_Wheel(event){
var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); // works with both Chrome and FireFox
var target = event.target;
}
|
Normally, the mouse wheel is used to scroll a web page.
However, when using the mouse to change the number in a field, the default action must be stopped.
For reasons beyond comprehension, with Firefox, the first time the event handler was called,
delta was zero. As a result event.preventDefault made it so that the
handler never did anything useful. The following fixed the page scrolling and
allowed the mouse wheel to perform like it did before.
if (delta!=0) event.preventDefault(); // works with both Chrome and FireFox
|
I have used this code before (without the if statement) without any problems.
I don't know why it is a problem now. Perhaps it is becuase I am using an input field,
and previously I used a canvas (to display a zoomable map)?
A more generic fix would be
if (delta==0) return; // zero values have no use
|
Javascript - write once, debug everywhere! (Just like Java!)
References
- How to Use the Mouse Wheel Event in HTML5 Pages
- This is the main source of the code above .. except that it suggests using return false;
- which does not work - to stop the page from scrolling.
- The onmousewheel event of JavaScript
- This is a very good page which explains, and fixes, some of the cross browser problems.
It includes
if (evt.preventDefault) //disable default wheel action of scrolling page
evt.preventDefault()
else
return false
|
In summary ??,
there appear to be 3 separate ways to handle the mouse wheel.
(This page is necessary because most references I found only mention one!)
- wheel
- mousewheel
- Firefox method
Author:
Robert Clemenzi