Similar to Sterling's answer, my first attempt was to kind of insert another checkpoint for the third color. This process, as in Sterling's solution, begins to precipitate the necessity of sub-functions. See it here: http://jsfiddle.net/5uU6y/1/
A better and more complete solution, in which you can declare multiple colors, can be achieved by creating an array which stores your beginning, ending, and color values that you can check against when the window is scrolled.
Here's that solution ( see it in action here: http://codepen.io/cgspicer/pen/tomvq/ )
$(document).ready(function(){
/**
requires http://code.jquery.com/color/jquery.color-2.1.0.js
*/
var colorsNPoints = [
{ 'begin' : 0, 'end': 100, 'color': 'rgb(220,20,60)' },
{ 'begin' : 100, 'end': 110, 'color': 'rgb(0,0,0)' },
{ 'begin' : 110, 'end': 210, 'color': 'rgb(50,205,50)' },
{ 'begin' : 210, 'end': 310, 'color': 'rgb(255,215,0)' },
{ 'begin' : 310, 'end': 410, 'color': 'rgb(220,20,60)' },
{ 'begin' : 410, 'end': 420, 'color': 'rgb(0,0,0)' },
{ 'begin' : 420, 'end': 520, 'color': 'rgb(50,205,50)' },
{ 'begin' : 520, 'end': 620, 'color': 'rgb(255,215,0)' },
{ 'begin' : 620, 'end': 720, 'color': 'rgb(220,20,60)' },
{ 'begin' : 720, 'end': 730, 'color': 'rgb(0,0,0)' },
{ 'begin' : 730, 'end': 830, 'color': 'rgb(50,205,50)' },
{ 'begin' : 830, 'end': 930, 'color': 'rgb(255,215,0)' }
];
$(document).scroll(function() {
var scrollPosition = $(this).scrollTop();
var currentRange = checkRange( scrollPosition, colorsNPoints );
if ( currentRange !== undefined ) {
console.log( currentRange );
var newColor = recalcColor( currentRange.prevColor, currentRange.nextColor, currentRange.progress );
$('body').css({ backgroundColor: newColor }, 0);
} else {
// do nothing, we're not within any ranges
}
});
// sub-functions
/**
* checks which, if any, of the scroll ranges the window is currently on
* returns an object containing necessary values
*/
function checkRange( yValue, rangesObj ) {
// loop over the object containing our ranges
for ( var i=0; i < rangesObj.length; i++ ) {
var rangeToCheck = rangesObj[i];
// check to see if we are within said range
if ( yValue >= rangeToCheck.begin && yValue <= rangeToCheck.end ) {
// set up a new object for refinement and return
var currentRangeObj = {};
currentRangeObj.prevColor = rangesObj[i-1] ? rangesObj[i-1].color : rangeToCheck.color; // store old color, falls back to range's color if no previous color exists
currentRangeObj.nextColor = rangeToCheck.color; // store new color
currentRangeObj.progress = calcPercentScrolled( rangeToCheck.begin, rangeToCheck.end, yValue ); //calculate the progress within the current range
return currentRangeObj;
} else {
}
}
}
/**
* calculates current percent scrolled
**/
function calcPercentScrolled( begin, end, current ) {
return (current - begin) / ( end - begin );
}
/**
* calculates new color
**/
function recalcColor( begin, end, factor ) {
var begin = $.Color( begin ),
end = $.Color( end );
var newRed = begin.red() + ( ( end.red() - begin.red() ) * factor );
var newGreen = begin.green() + ( ( end.green() - begin.green() ) * factor );
var newBlue = begin.blue() + ( ( end.blue() - begin.blue() ) * factor );
return $.Color( newRed, newGreen, newBlue );
}
});
Hope this helps!