Skip to content

Mousewheel Support #71

Closed
fourgood opened this Issue Mar 2, 2012 · 19 comments

2 participants

@fourgood
fourgood commented Mar 2, 2012

Is it possible to integrate mousewheel support?
I already tried this plugin https://github.com/brandonaaron/jquery-mousewheel/
but can`t get it to work.

I just need to know the syntax for triggering the the 'goForward' / 'goBack' event from outside.

@fourgood
fourgood commented Mar 2, 2012

got it to work:

    $(document).ready(function() {
    mb = $('#slider').data('movingBoxes');

    $('.mb-inside')
        .mousewheel(function(event, delta, deltaX, deltaY) {

            if (delta > 0)
                mb.goBack();
            else if (delta < 0)
                mb.goForward();

            return false; // prevent default
        });
    });

only issue that i can scroll only one after another. means that the slide have to be completed after another can occure, which makes it pretty slow to scroll thorugh many images.

@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

Hi fourgood!

I actually ended up modifying the plugin core a bit to prevent rapid calls to those functions, it totally messes up the appearance otherwise. But I did modify your code a bit to change the animation speed depending on the amount of wheel scroll... it's not perfect and yes, you can still only scroll one panel at a time, but it's much faster. Demo

$('#slider').movingBoxes({
    buildNav: true,
    // if true, navigation links will be added
    preinit: function(e, mb, tar) {
        var defaultTime = 500;
        mb.$window.mousewheel(function(event, delta) {

            // Modify animation time based on delta
            // delta values are varied across browsers/OS,
            // so we need to normalize it somehow
            var newTime, direction = (delta < 0) ? -1 : 1,
                ab = Math.abs(delta),
                newDelta = ab * 10;
            if (ab > 1000) { // probably never be this high; but just in case
                newDelta = 100;
            }
            if (ab > 100 && ab < 1000) {
                newDelta = ab / 10;
            }
            if (ab < 100) {
                newDelta = ab * 10;
            }

            // end up with a time between 50 and defaultTime
            newTime = Math.floor(Math.abs(defaultTime * 10 / newDelta));
            newTime = (newTime > defaultTime) ? defaultTime : (newTime < 50) ? 50 : newTime;

            // change animation speed
            mb.options.speed = newTime;
            // using change because it includes a callback
            mb.change(mb.curPanel - direction, function() {
                // change speed back after completed
                mb.options.speed = defaultTime;
            });
            return false; // prevent default
        });
    }
});​
@fourgood
fourgood commented Mar 2, 2012

that works great so far. but how do i combine that with my function for creating the NAV arrows which is also in the preinit.

function(e, slider, tar){

            slider.$nav.prepend('<span class="prev"></span>').append('<span class="next"></span>').find('.prev, .next').click(function() {
                slider[ ($(this).hasClass('next')) ? 'goForward' : 'goBack']();
@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

Think of the callback function as a block of code, add it before or after:

preinit : function(e, mb, tar){
    // nav arrow code

   //  mousewheel code
}

or the full version ;)

preinit: function(e, mb, tar) {

    // nav arrow code
    // from https://github.com/chriscoyier/MovingBoxes/issues/68#issuecomment-4195656
    mb.$nav
        .prepend('<span class="prev"></span>')
        .append('<span class="next"></span>')
        .find('.prev, .next').click(function() {
            mb[ ($(this).hasClass('next')) ? 'goForward' : 'goBack']();
        });

    //  mousewheel code
    var defaultTime = 500;
    mb.$window.mousewheel(function(event, delta) {

        // Modify animation time based on delta
        // delta values are varied across browsers/OS,
        // so we need to normalize it somehow
        var newTime, direction = (delta < 0) ? -1 : 1,
        ab = Math.abs(delta),
        newDelta = ab * 10;
        if (ab > 1000) { // probably never be this high; but just in case
            newDelta = 100;
        }
        if (ab > 100 && ab < 1000) {
            newDelta = ab / 10;
        }
        if (ab < 100) {
            newDelta = ab * 10;
        }

        // end up with a time between 50 and defaultTime
        newTime = Math.floor(Math.abs(defaultTime * 10 / newDelta));
        newTime = (newTime > defaultTime) ? defaultTime : (newTime < 50) ? 50 : newTime;

        // change animation speed
        mb.options.speed = newTime;
        // using change because it includes a callback
        mb.change(mb.curPanel - direction, function() {
            // change speed back after completed
            mb.options.speed = defaultTime;
        });
        return false; // prevent default
    });
}
@fourgood
fourgood commented Mar 2, 2012

i tried that, but the
``` function(e, mb, tar)


defines mb and not slider, so it doesnt work
@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

Opps, just change slider to mb... I updated the code above.

@fourgood
fourgood commented Mar 2, 2012

i tried that too, but now the speed is slow again ;( so i thought i was wrong
http://kieferundkiefer.de/?p=163

@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

Seems to work fine for me, just right in Chrome and almost too fast in Firefox. Is there a specific browser that you are seeing it slow in?... Like I said, it's not prefect, every browser returns a different delta so there is no ideal solution.

@fourgood
fourgood commented Mar 2, 2012

im using firefox 10.0.2 on a Win7 and a WinXP machine.
Without the arrows it was much faster.

it seems that in the very first moment when the page loads, the first movement is fast.
then it stucks between every slide.

@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

It's going to pause between slides no matter what, because the animation stops when it centers the panel.

If we got rid of the stop, it could stack up too many animations it could mess up the look of the boxes, that is if they are resizing. I guess I could try tossing in a stop() animation in there and see what happens...

@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

Hmm, ok that seemed to work much better, it might even be too fast... so I just pushed a new version where I added a new option named stopAnimation... here is the new much shorter code and demol:

$('#slider').movingBoxes({
    buildNav: true,
    stopAnimation: true,
    preinit: function(e, mb, tar) {
        mb.$window.mousewheel(function(event, delta) {
            mb.change(mb.curPanel + (delta < 0 ? 1 : -1));
            return false; // prevent default
        });
    }
});​

Make sure you use shift + browser reload to clear the browser cache.

@fourgood
fourgood commented Mar 2, 2012

wow! you did it.
do you have paypal so i can contribute for your project work?

@Mottie
CSS-Tricks member
Mottie commented Mar 2, 2012

YAY! So is it okay then to close this issue?

Oh, and I was thinking that if the scrolling is too fast you could throttle the mousewheel function a bit to slow it down. Here is a demo and the code; change the throttledDelay value (in milliseconds) by making the number bigger to slow it down more:

$('#slider').movingBoxes({
    buildNav: true,
    stopAnimation: true,
    preinit: function(e, mb, tar) {
        var throttled = false,

        // increase the throttleDelay to slow down the mouse scrolling
        throttledDelay = 100; // milliseconds

        mb.$window.mousewheel(function(event, delta) {
            if (!throttled) {
                mb.change(mb.curPanel + (delta < 0 ? 1 : -1));
                throttled = true;
                setTimeout(function(){
                    throttled = false;
                }, throttledDelay);
            }
            return false; // prevent default
        });
    }
});​

It really isn't necessary to give donate, but if you want my paypal is the same as my gmail address; user name wowmotty.

@fourgood
fourgood commented Mar 3, 2012

yes, you can close this issue :)

@Mottie Mottie closed this Mar 3, 2012
@fourgood
fourgood commented Mar 4, 2012

i am so sorry to open this again. but ive another small issue that just came up.
if i click the side panels it slides very abrupt. only if i hold the mouse button down the animation finishes smoothly. so, a short click leads to abrupt sliding now.

@Mottie
CSS-Tricks member
Mottie commented Mar 4, 2012

I tested the demo I posted above, and when I clicked on the side panels, they slid in at a normal rate... did you do something different with the code?

@fourgood
fourgood commented Mar 4, 2012

hmm, actually your demo doesnt slide at all if you hold the mouse button. i will have to take a look at my code again.

@fourgood
fourgood commented Mar 4, 2012

cant find it. probably it has something to do with "stopAnimation: true, ". if i delete this, the first click is very abrupt, but the second and all the following are smooth.

http://kieferundkiefer.de/

update: it seems to be a firefox/IE issue. in chrome it works fine.

and another thing, sometimes at the end when it should loop it scrolls backwards to the first panel. just sometimes.

this is my code:

    <script>
    $(document).ready(function() {

      if ($.cookie('current-panel') == null ){
       $.cookie('current-panel', 1, { expires: 1 }); 
      } 

        $('#slider').movingBoxes({
            wrap         : true,   // if true, the panel will "wrap" (it really rewinds/fast forwards) at the ends
            buildNav     : true,   // if true, navigation links will be added
            initAnimation: false,
            hashTags: false,
            reducedSize  : 1.0,
            speed: 1000,
            startPanel: $.cookie('current-panel'),

            stopAnimation: true, 

            initChange   : function(e, slider, tar){

                var t = (tar < 1) ? slider.totalPanels : (tar > slider.totalPanels) ? 1 : tar,
                $tar = slider.$panels.eq(t);
                // hide non-current panel text
                slider.$panels.not($tar).find('span').stop().animate({ color: "#fff" }, 500);
                // show current panel text
                $tar.find('span').stop().animate({ color: "#555" }, 500); },

            navFormatter : function(index, panel){ _title=panel.find('span').text();  _url=panel.find('a img').attr('src');
                return "<div class='formInfo' id='"+_title+"' title='"+_title+"'><div class='nav_btn'></div><span class='tip' style='display: none'><img width='60' height='60' class='imag' src='"+_url+"' /><br />"+_title+"</span></div>";  },

            preinit: function(e, mb, tar) {

            mb.$panels.filter(':not(:eq(' + (tar) + '))').find('span').css('color', '#fff');

                // nav arrow code
                mb.$nav
                    .prepend('<span class="prev"></span>')
                    .append('<span class="next"></span>')
                    .find('.prev, .next').click(function() {
                        mb[ ($(this).hasClass('next')) ? 'goForward' : 'goBack']();
                    });

                //  mousewheel code
                var throttled = false,
                throttledDelay = 200;

                mb.$window.mousewheel(function(event, delta) {
                if (!throttled) {
                mb.change(mb.curPanel + (delta < 0 ? 1 : -1));
                throttled = true;
                setTimeout(function(){
                    throttled = false;
                }, throttledDelay);
            }
            return false; // prevent default
        });
            }
        });

    });
    </script>
@Mottie
CSS-Tricks member
Mottie commented Mar 4, 2012

Hmm, I think it has something to do with clicking on the panel after it has already started moving right? That is happening because the first click starts the animation to bring the panel to the center, but a second click does the same thing, except it forces the first animation to complete immediately. I'm not sure if there's an easy way around it because if we add the "current" class immediately to the panel, then the second click would cause it to open the link. I guess the easiest solution would be to stop double clicking...

As for the wrap not working, that's also because of aggressive mouse wheel scrolling. When you get to the last slide and scroll the mouse wheel, it needs to finish the animation before it resets Moving Boxes on the first panel to make it appear that it is infinitely scrolling. Well, as before, moving the mouse quickly will cause it to complete the animation and now it wants to go to the second panel, which is now to the left of it's current position and thus it scrolls left.

Both of the issues you brought up do not have an easy or straight-forward fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.