-
Notifications
You must be signed in to change notification settings - Fork 1
/
rolly-scrolly.js
87 lines (75 loc) · 2.47 KB
/
rolly-scrolly.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
function rollyScrolly(opt){
/*
rollyScrolly tracks what percentage of the screen's real estate you've scrolled through
and executes functions for discrete frames of that scrollable area
see https://github.com/WilliamsNY/rolly-scrolly/blob/master/README.md for instructions on its usage
*/
var $window=$(window);
var $container=$(opt.container||'body');
var state={
position:0,
lastPosition:0,
range:$container.height(),
frames:opt.frames-1||1000, // subtract one here because we include the zero frame
container:$container,
scrolltop:0,
};
var events=opt.events||{};
var stack=opt.stack||[];
updateViewportHeight();
// execute every function within the stack when you scroll
// functions receive the 'state' object as an argument
// as well as an integer representing their position in the stack (probably useless)
$window.scroll(function(){
var hasChangedPosition=false;
// guarantee execution of all events
(function(state){
var top=state.scrollTop=$window.scrollTop();
var temp=Math.floor((top/state.range)*state.frames);
if(state.position !== temp){
hasChangedPosition=true;
// make sure intermediary events get called...
(function(){
if(temp > state.position){
while(state.position < temp){
state.position++;
if(events[state.position]){
events[state.position].func(state,0);
}
}
}else{
while(state.position > temp){
state.position--;
if(events[state.position]){
events[state.position].func(state,0);
}
}
}
}());
state.position=temp;
}
}(state));
// and if the position has changed, then call every function in the stack.
if(hasChangedPosition){
stack.forEach(function(item,index){
item.func(state,index);
});
}
});
// we're tracking how far we can scroll, so we need to know what amount
// of the document is visible within the viewport
$window.resize(updateViewportHeight);
// purely for side effects
function updateViewportHeight(){
state.viewportHeight= Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
state.range=$container.height()-state.viewportHeight;
};
// objects are passed by reference, so return a reference to anything
// that you might want to alter after initialization
return {
state:state,
$container:$container,
events:events,
stack:stack,
};
}