How to enforce a "smooth scrolling" rule for mousewheel, jQuery?
Asked Answered
C

7

25

How are you? My Question:

How can I control or specify the way a document scrolls to the position of desire described by either the mouse scrollwheel, and/or grabbing the scrollbar. What I want would be to overcome the particular default method of page scrolling.
As it currently works the page jumps right to x# of pixels down per 'notch' that is progressed on the scrollwheel. Or goes directly to where you drag the scroll bar. What i'm looking for is a simple extension to jquery that can apply certain scrolling rules.The principals are simple. Imposed acceleration, this would prevent the page from moving too fast without first accelerating. settable as a rate of in px/sec- with the option to apply easing functions...There is a maximum px/sec that the page can slide/move/drag. and thirdly is a deceleration rule, applied as the page approaches it's destination position (in %, px?). This may have to be calculated in one of many ways, and may be trickier. ie when scrolling the last 25 pixels to the destination position, the deceleration applys. There's more... The main concern I'd want to prepare for would be ensuring that small page scrolls we're supported fully and not glitchy.
What sort of jQuery approaches could be used to control the document in this way? _kyle

Update::: Thanks For following this Q, if you are. Great News. Found a great plugin that hopefully can be handled to be supporting the desired effects, yo! I've implemented a whole page container and used this nifty jScrollPane script to commandeer if you will the scrolling of the page http://jscrollpane.kelvinluck.com/fullpage_scroll.html

There is already a big difference in the performance of the page. Each scroll notch from the wheel is a third to a half of the browsers native scroll notch, so it moves slower, which is fine, surly that's adjustable.
We still have the stall-stall-stall method of page movement, though.

I myself write javascript, but more it's like I re-write it. What I think needs to be done is a "queue" built of pixels to be scrolled along a page, with the total time compounded: and then an animation footprint defined and executed as three phases, an in easing acceleration, maxscrollspeed phase, and decel phase.

Could anybody offer any suggestions as to how we

  1. Detatch the mousescrollwheel from its native function of scrolling the page.

  2. listen for notches of the mousescroll; and in the event of a notch: initialize the corefunction to start the movement of the page, but also listen for and add additional notch clicks to "queue" that is re-calulated and applied to the scroll of the window replacing the previous totaldistancetoscroll, before calculating the next totaldistancetoscroll, which provides a way to anticipate the destination and decelerate. The corefunctions to start movement wouldn't want to be restarted, cause multiple notch clicks will probably happen while accelerating, but just a recalculated when and where to decelerate should be applied.

Sorry again for not posting any actual code yet, not exactly sure where to start and was hoping someone might know if mwintent will work for this and if so: might also have some ideas how to apply a deceleration to the scroll, which seems to be the only two difference between the desired effect and the state of the current plug-ins that are similar.

Colony answered 6/4, 2011 at 2:5 Comment(4)
This sounds like it would be pretty irritating for the user.Tiatiana
Are you thinking of iPhone-like scrolling?Dichogamy
Yes verymuch like iphone-like scrolling, thanks for the link on that. Except supporting mouseweel scrolling smoothly, and not supporting click dragging of the page... nore would the 'overthrow' effect be wanted... the page would stop where it was desire and not keep 'floating' on. =)Colony
Possible duplicate: #9142990Ruscio
P
14

What I wanted to do was to simulate browser's smooth scrolling on browsers that don't support it natively, has it turned off by default or has bad implementation of it.

Thanks to lumbric's answer I've came up with this solution:

$(function () {

    var top = 0,
        step = 55,
        viewport = $(window).height(),
        body = $.browser.webkit ? $('body') : $('html'),
        wheel = false;


    $('body').mousewheel(function(event, delta) {

        wheel = true;

        if (delta < 0) {

            top = (top+viewport) >= $(document).height() ? top : top+=step;

            body.stop().animate({scrollTop: top}, 400, function () {
                wheel = false;
            });
        } else {

            top = top <= 0 ? 0 : top-=step;

            body.stop().animate({scrollTop: top}, 400, function () {
                wheel = false;
            });
        }

        return false;
    });

    $(window).on('resize', function (e) {
        viewport = $(this).height();
    });

    $(window).on('scroll', function (e) {
        if (!wheel)
            top = $(this).scrollTop();
    });

});

Put some content on your page long enough to have scrollbars. Then use your mouse wheel. It works on every browser. I've used jQuery-1.7.2 and the mousescroll plugin mentioned in the lumbric's post.

The step var means how many pixels to scroll on every mouse wheel event. ~55 pixels is what I've found to be the default value on most systems.

Also you may want to change the speed for the animation, other than that the rest of the code logic is needed to get the things work properly.

EDIT: Note that I have extracted the above functionality into a convenience jquery plugin.

Persia answered 15/6, 2012 at 21:11 Comment(1)
Problem with this solution is that if you've got some elements on page that have their own scrollbars, they will be ignoredDunleavy
G
4

I had a very simmilar problem. I wanted to change the scroll function of a normal page. I want every scroll to be exactly of an specific height so that the page stops in very specific positions only.

I realized it in the following way:

1. Used Plugins

Download and include the following 2 jQuery plugins and jQuery itself:

2. Mousewheel event

The easiest way is to use the mousewheel plug in that way:

$('body').mousewheel(function(event, delta) { /* code here */ });

The variable delta is then negative or positive, depending if the wheel was scrolled up or down. If you return false I think (!) it disables the normal scroll.

3. Scroll method

In order to scroll the page I used scrollTo, but any other plugin (like Smooth Scroll suggested in the other answer) should also do it.

4. Complete code

Place this in the head part of you HTML-File:

<script type="text/javascript" src="jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="jquery.scrollTo-1.4.2-min.js"></script>
<script type="text/javascript" src="jquery.mousewheel.min.js"></script>
<script type="text/javascript">
    $(document).ready(function() {          
        $('body').mousewheel(function(event, delta) {
            # This if might not be very elegant!
            if (delta < 0) {
                $('body').scrollTo('+=100', 1500 );
            }
            else
                $('body').scrollTo('-=100', 1500 );

            return false;
        });
    });
</script>

5. Demo

I created a demo here: http://pastehtml.com/view/ba0ziusqk.html

Girder answered 9/10, 2011 at 17:7 Comment(3)
This is a good start, but I can't seem to figure out how to make it a bit smoother (e.g. If you scroll down several times, it'll scroll a little, slow to a stop, then scroll a little, then slow to a stop, etc...)Ergot
This was exactly what I wanted to do (it's not a normal page). If you want a smooth scroll feeling, you have to change the easing for scrollTo. Read this to learn more about it. You probably need linear easing, so this would be the command: jQuery('body').scrollTo('-=404', 1500, {easing : 'linear'} ) But a Warning: If you do this, people who want to scroll fast through your page might be really annoyed and leave again!Girder
Well.. I just noticed that my last comment might not be so usefull. If you really want to make scrolling smooth, why not using the plugin mentioned by Alex?Girder
M
2

You want to give this one a try

https://github.com/galambalazs/smoothscroll-for-websites

it has nice settings to adjust the animation and seems to be well maintained.

// Scroll Variables (tweakable)
var defaultOptions = {

    // Scrolling Core
    frameRate        : 100, // [Hz]
    animationTime    : 1200, // [ms]
    stepSize         : 80, // [px]

    // Pulse (less tweakable)
    // ratio of "tail" to "acceleration"
    pulseAlgorithm   : true,
    pulseScale       : 4,
    pulseNormalize   : 1,

    // Acceleration
    accelerationDelta : 50,  // 50
    accelerationMax   : 3,   // 3

    // Keyboard Settings
    keyboardSupport   : true,  // option
    arrowScroll       : 50,    // [px]

    // Other
    touchpadSupport   : false, // ignore touchpad by default
    fixedBackground   : true, 
    excluded          : ''    
};
Miltie answered 28/8, 2015 at 9:41 Comment(1)
This is the best script I have found, so far. It does it nice and smoothly, yet does not hijack the default scrolling. It actually seems to work exactly as the default scrolling, yet at the end, it smooths it down. Best suggestion! See codepen.io/AartdenBraber/pen/YVXVoB for a testdrive.Magdaleno
P
2

here is a good solution check this out http://ataredo.com/morphology/lucidscroll/

<script src="file-directory/jquery.js"></script>
<script src="file-directory/lucid.js"></script>

<script>
$(window).on('load', function() {

  $(this).impulse();
});
</script>
Partlow answered 24/9, 2015 at 12:30 Comment(0)
J
1

Karl Swedberg has made a jQuery plugin called Smooth Scroll, which sounds like it may be just what you're after.

Jamestown answered 6/4, 2011 at 2:10 Comment(1)
Ahh... Thank you, i actually looked for any plugins related to smooth scrolling and jquery and didn't run across anything like this, which looks somewhere for me to start. I want to figure out to how get it to apply to when the mousewheel moves the page or when the page is dragged directly, i'll have to look at that mousewheel intent script. Thank you again =)Colony
A
1

my solution with Mobile effect

    <div id="parent">
    <div id="child">aaa aaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaa</div>

        #parent {
        width: 300px;
        height: 300px;
        background-color: #aaa;
        margin: auto auto;
        overflow: hidden;
    }
    #child {
        width: 200px;
        height: 800px;
        background-color: #999;
        margin: auto auto;
        text-align: justify;
        position: relative;
        top: 0;
        -webkit-transition: all 0.5s ease-out;
}




$('#parent').bind('mousewheel', function (e) {
        if (!(e.originalEvent.wheelDelta == 120)) {
            var top = parseInt($("#child").css("top"));
            $("#child").css("top", (top - 100) + "px");
            top = parseInt($("#child").css("top"));
            if (top <= -500) {
                setTimeout(function () {
                    $("#child").css("top", "-500px");
                }, 100);
            }
        } else {
            var top = parseInt($("#child").css("top"));

            $("#child").css("top", (top + 100) + "px");
            top = parseInt($("#child").css("top"));
            if (top >= 0) {
                setTimeout(function () {
                    $("#child").css("top", "0");
                }, 100);
            }
        }
    });

THE DEMO

According answered 7/9, 2013 at 6:58 Comment(0)
T
0
var $window              = $(window),
    scrollDistance   = 300,
    scrollSpeed      = 500,
    scrollEffect     = 'swing',
    scrollAmount     = 1,
    smoothScroll;

if (! ('ontouchstart' in document.documentElement) && ! $('body').hasClass('modal-open')) {

        $window.on("mousewheel DOMMouseScroll", function (event) {

            event.preventDefault();

            if (smoothScroll) {

                // Start scrolling while waiting for final scoll amount (user stopped wheeling)
                if (scrollAmount == 1) {
                    var delta = event.originalEvent.wheelDelta / 120 || -event.originalEvent.detail / 3;
                    var finalScroll = $window.scrollTop() - parseInt(delta * (scrollDistance * scrollAmount));

                    $('html, body').stop().animate({ scrollTop: finalScroll }, scrollSpeed, scrollEffect);
                }

                // Increase scroll amount
                scrollAmount++;

                // Clear current timeout
                clearTimeout(smoothScroll);
            }

            // Set animated scroll
            smoothScroll = setTimeout(function() {

                var delta = event.originalEvent.wheelDelta / 120 || -event.originalEvent.detail / 3;
                var scrollTop = $window.scrollTop();
                var finalScroll = scrollTop - parseInt(delta * (scrollDistance * scrollAmount));

                // Reset scroll amoount
                scrollAmount = 1;

                $('html, body').stop().animate({ scrollTop: finalScroll },
                    (scrollSpeed*scrollAmount),
                    scrollEffect
                );

                // Clear timeout holder
                smoothScroll = null;

            }, 100);

        });
}
Trauner answered 15/5, 2015 at 16:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.