ChrisK ChrisK - 3 months ago 8
jQuery Question

Collect Mousewheeler trigger and then call function

I build a simple zoom effect with javascript/jquery but struggle to make this one a bit smoother.

document.addEventListener("mousewheel", mouseWheelHandler, false);
document.addEventListener("DOMMouseScroll", mouseWheelHandler, false);
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));


When
delta > 0
I increase the width of my container, when
delta < 0
I decrease the width of my container.
See Code snippet for basic example:



document.addEventListener("mousewheel", mouseWheelHandler, false);
document.addEventListener("DOMMouseScroll", mouseWheelHandler, false);
function mouseWheelHandler(e) {
var current_width = $('div').width();
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if(delta == -1) {
$('div').css('width', current_width / 1.1);
} else {
$('div').css('width', current_width * 1.1);
}
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background-image:url(https://placehold.it/500x500);height:500px;width:500px;">





I know want that to collect the scrolls a user performances and only scroll once.
I tried using
setTimeout()
and set it to 1000ms, collect all
delta
values into one variable and then zoom in that often:



document.addEventListener("mousewheel", mouseWheelHandler, false);
document.addEventListener("DOMMouseScroll", mouseWheelHandler, false);
var zoom_factor = 0;
function mouseWheelHandler(e) {
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
setTimeout(function(){
zoom_factor = zoom_factor + delta
console.log(zoom_factor);
}, 1000);
zoom(zoom_factor);
}


function zoom(zoom_factor) {
var current_width = $('div').width();
var new_width = current_width;
if(zoom_factor > 0) {
for(var i = 0; i < zoom_factor; i++) {
new_width = new_width * 1.1
}
} else if (zoom_factor < 0) {
zoom_factor = zoom_factor * -1
for(var i = 0; i < zoom_factor; i++) {
new_width = new_width / 1.1
}
}
$('div').css('width',new_width);
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background-image:url(https://placehold.it/500x500);height:500px;width:500px;">





This doesn't work because even when the timeout is still passing, the zoom effects are all triggered.

Is there a way to call the
zoom()
after the
setTimeout()
is finished and is only called once?

Answer

Try this:

var zoom_factor = 0;
var timeout;
function mouseWheelHandler(e) {
  var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
  // reset timeout
  clearTimeout(timeout);

  timeout = setTimeout(function(){
    // call zoom() once
    zoom(zoom_factor);

    // reset zoomfactor
    zoom_factor = 0;
  }, 1000);

  // Calculate zoom factor
  zoom_factor = zoom_factor + delta;
}
Comments