Kinetic Scrolling

by Gregory Guidero

HTML

<div id="outer">
    <div id="inner">
            Item 1
        <br /><br /><br />
            Item 2
        <br /><br /><br />
            Item 3
        <br /><br /><br />
            Item 4
        <br /><br /><br />
            Item 5
        <br /><br /><br />
            Item 6
        <br /><br /><br />
            Item 7
        <br /><br /><br />
            Item 8
        <br /><br /><br />
            Item 9
        <br /><br /><br />
            Item 10
        <br /><br /><br />
            Item 11
        <br /><br /><br />
            Item 12
        <br /><br /><br />
            Item 13
        <br /><br /><br />
            Item 14
        <br /><br /><br />
    </div>
</div>

CSS

#outer
{
    height:340px;
    background:#000;
    width:220px;
    overflow:auto;
}
#inner
{
    height:880px;
    width:100%;
    background:#333;
    color:#fff;
}

JavaScript

/* IE Friendly */
var time = 0;
var isScrolling = false;
var inertiaTimer = null;
var outer = document.getElementById('outer');
function inertia(pos,decay)
{
    var timeNow = Date.now();
    timeNow = Math.exp((timeNow - time)/1000);
    /* Increase and decrease scroll inertia here by changing 0.95, the higher
     * the number the longer and faster it will go and lower the number
     * the slower and less distance it will go, 0.95 is the sweet spot*/
    decay = (decay*(Math.pow(0.98,timeNow)));
    decay = (Math.floor(100*decay+.5))/100;
    pos = pos-decay; 
    
    if(typeof outer.scrollTop != 'undefined')
    {
        outer.scrollTop = pos;
    }
    else
    {
        outer.offsetTop = pos+'px';
    }
    
    if(decay > 0.2 || decay < -0.2)
    {
        inertiaTimer = setTimeout(function(){inertia(pos,decay);},1000/60);
    }
    else
    {
        isScrolling = false;
    }
}

var scroll = function(e)
{
    if (e == null)
    {
        e = window.event;
    }
    if(typeof e.preventDefault != 'undefined')
    {
        e.preventDefault();
    }
     var delta = 0;
    if (typeof e.wheelDelta != 'undefined')
    {
        delta = e.wheelDelta/60;
    }
    else if (typeof e.detail != 'undefined')
    {
        delta = -e.detail/2;
    }
    if(typeof outer.scrollTop != 'undefined')
    {
        var pos = outer.scrollTop
    }
    else
    {
        var pos = outer.offsetTop;
    }
    
    var decay = delta*10;
    time = Date.now();
    if(isScrolling)
    {
        clearTimeout(inertiaTimer);
    }
    isScrolling = true;
    inertia(parseInt(pos),decay);
    return false;
}
if(typeof document.onmousewheel == 'undefined')
{
    outer.addEventListener('DOMMouseScroll', scroll);
}
else
{
    outer.onmousewheel = scroll;
}