Skip to content

Commit 980361d

Browse files
authored
Merge pull request #70 from m-code12/scroll-animations
Final Changes in scroll animations
2 parents b155af2 + 2830722 commit 980361d

File tree

2 files changed

+387
-30
lines changed

2 files changed

+387
-30
lines changed

animate-scroll/animate-scroll.js

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
/*
2+
Plugin Name: jQuery Animation Scroll Plugin
3+
Author: Jason Lusk
4+
URI: JasonLusk.com
5+
Example:
6+
<p data-animate-scroll='{"scaleX": "1.5","scaleY": "1.5","x": "-10","y": "-10","rotation": "-3","alpha": "1","easingType": "Cubic.easeOut","duration": "1"}'>test</p>
7+
*/
8+
(function($, window, document) {
9+
'use strict';
10+
var $window = $(window),
11+
attachEvent = document.attachEvent,
12+
//init scroll-event only once for better performance -> save target-data first in arrays
13+
animateScroll = {
14+
throttles: {},
15+
animations: [],
16+
bind: function(el, options) {
17+
$(el).on('reverse play', function(evt) {
18+
if(evt.type == 'play' && !options.reverse){
19+
return true;
20+
}
21+
// animate target object based on viewport check event
22+
var $this = $(this),
23+
$timeline = $this.data('tween'),
24+
action;
25+
if (!!$timeline && evt.type != action) {
26+
if (!options.animateAll && evt.type == 'play') {
27+
$timeline.progress(1, true);
28+
}
29+
$timeline[evt.type]();
30+
action = evt.type;
31+
}
32+
});
33+
if (!!animateScroll.throttles.watch) {
34+
$window.find('body').andSelf().on('scroll resize orientationchange touchend gestureend check', function(e) {
35+
// trigger viewport animation check
36+
animateScroll.throttles.scroll = (animateScroll.throttles.scroll == null) && setTimeout(function() {
37+
animateScroll.inview(e.type == 'resize' || e.type == 'orientationchange');
38+
animateScroll.throttles.scroll = null;
39+
}, 101);
40+
});
41+
}
42+
animateScroll.throttles.watch = el;
43+
},
44+
check: function(target) {
45+
// is stored original element position centered within the viewport
46+
var tObj = $(target),
47+
vTop = $window.scrollTop(),
48+
vBottom = vTop + $window.height(),
49+
elTop = tObj.data('originalOffset').top,
50+
elBottom = elTop + parseInt(tObj.data('originalSize').height);
51+
animateScroll.throttles.transition = null;
52+
return (vTop < elBottom && elBottom < vBottom) || (vTop < elTop && elTop < vBottom) ? 'reverse' : 'play';
53+
},
54+
update: function($this, $timeline) {
55+
var newOffset = $this.offset(),
56+
oldOffset = $this.data('originalOffset') || {
57+
top: 0
58+
};
59+
if (newOffset.top != oldOffset.top) {
60+
// update saved offset and size
61+
$this.data({
62+
'originalOffset': newOffset,
63+
'originalSize': {
64+
width: $this.width(),
65+
height: $this.height()
66+
}
67+
});
68+
}
69+
},
70+
inview: function(resize) {
71+
animateScroll.animations.each(function() {
72+
var $this = $(this),
73+
$timeline = $this.data('tween');
74+
// update trigger position
75+
if (!!resize) {
76+
setTimeout(function() {
77+
animateScroll.update($this, $timeline);
78+
// trigger animation event
79+
$this
80+
.trigger(animateScroll.check($this));
81+
}, 250);
82+
} else {
83+
// trigger animation event
84+
$this
85+
.trigger(animateScroll.check($this));
86+
}
87+
});
88+
},
89+
init: function(animations, options) {
90+
91+
// add resize event to body
92+
addResizeListener($('body')[0], function() {
93+
$('body').trigger('resize');
94+
});
95+
96+
// function to initialize plugin and pass custom variables from html5 data attributes
97+
animations.each(function() {
98+
var $el = $(this);
99+
$el
100+
.animateScroll($.extend({}, options, $el.data('animate-scroll')));
101+
})
102+
.promise()
103+
.done(function() {
104+
animateScroll.inview();
105+
});
106+
},
107+
setup: function($this, $parent, options) {
108+
// setup parent element perspective
109+
TweenMax.set($parent, {
110+
transformPerspective: options.transformPerspective,
111+
onComplete: function() {
112+
$parent
113+
.css({
114+
'perspective': options.transformPerspective
115+
});
116+
}
117+
});
118+
$this
119+
.addClass('animateScroll')
120+
.css({
121+
"-webkit-transform": "translate3D(0,0,1px)"
122+
});
123+
$this
124+
.data({
125+
'originalOffset': $this.offset(),
126+
'originalSize': {
127+
width: $this.width(),
128+
height: $this.height()
129+
},
130+
'tween': new TimelineMax({
131+
paused: true,
132+
onComplete: function() {
133+
animateScroll.update($this, this);
134+
}
135+
})
136+
.to($this, options.duration, {
137+
transformStyle: 'preserve-3d',
138+
transformOrigin: options.transformOrigin,
139+
x: options.x,
140+
y: options.y,
141+
scaleX: options.scaleX,
142+
scaleY: options.scaleY,
143+
rotation: options.rotation,
144+
rotationX: options.rotationX,
145+
rotationY: options.rotationY,
146+
autoAlpha: options.alpha,
147+
delay: options.delay,
148+
z: options.z,
149+
force3D: options.force3D,
150+
ease: options.easingType
151+
}).progress(1, false)
152+
})
153+
.promise()
154+
.done(function() {
155+
animateScroll
156+
.bind($this, options);
157+
});
158+
}
159+
};
160+
$.fn.animateScroll = function(opts) {
161+
//set up default options
162+
var defaults = {
163+
transformPerspective: 1000, // Parent Transform Perspective
164+
lazyLoad: false, // Lazy Load Images (experimental)
165+
animateAll: false, // Animate elements outside of viewport?
166+
reverse: false, // Allow elements reverse animation state
167+
transformOrigin: '50% 50%', // Transform Origin X/Y Position
168+
x: 0, // Horizontal offset in px
169+
y: 0, // Vertical offset in px
170+
scaleX: 1, // Scale X position
171+
scaleY: 1, // Scale Y position
172+
rotation: 0, // Rotation in degrees
173+
rotationX: 0, // Rotation X position
174+
rotationY: 0, // Rotation X position
175+
alpha: 0.9, // Opacity from 0.0-1
176+
delay: 0, // Animation Delay
177+
z: 0.1, // Z position
178+
force3D: true, // Force 3D Hardware
179+
easingType: 'Back.easeInOut', // Animation easing Type
180+
duration: 0.3 // Animation diration in seconds
181+
};
182+
183+
var options = $.extend({}, defaults, opts);
184+
if (this[0] != document) {
185+
186+
this.each(function(index) {
187+
options = $.extend({}, defaults, opts);
188+
var $this = $(this),
189+
$parent = $this.parent();
190+
if (options.lazyLoad && $this.is('img')) {
191+
$this.on('load', function() {
192+
animateScroll
193+
.setup($this, $parent, options);
194+
});
195+
} else {
196+
animateScroll
197+
.setup($this, $parent, options);
198+
}
199+
});
200+
} else {
201+
animateScroll
202+
.animations = $('[data-animate-scroll]');
203+
animateScroll
204+
.init(animateScroll.animations, options);
205+
}
206+
}
207+
208+
// element resize listener [add|remove]ResizeListener(resizeElement, resizeCallback);
209+
// based on https://github.com/sdecima/javascript-detect-element-resize
210+
if (!attachEvent) {
211+
var createStyles = function() {
212+
if (!!createStyles) {
213+
var n = document.head || document.getElementsByTagName("head")[0],
214+
r = document.createElement("style"),
215+
css = '.r-t {\
216+
visibility: hidden;\
217+
}\
218+
.r-t, .r-t > div, .c-t:before {\
219+
content: " ";\
220+
display: block;\
221+
position: absolute;\
222+
top: 0;\
223+
left: 0;\
224+
height: 100%;\
225+
width: 100%;\
226+
overflow: hidden\
227+
}\
228+
.r-t > div {\
229+
background: #eee;\
230+
overflow: auto\
231+
}\
232+
.c-t:before {\
233+
width: 200%;\
234+
height: 200%\
235+
}';
236+
r.type = "text/css";
237+
if (r.styleSheet) {
238+
r.styleSheet.cssText = css
239+
} else {
240+
r.appendChild(document.createTextNode(css))
241+
}
242+
n.appendChild(r)
243+
return r.sheet || false;
244+
} else {
245+
return false;
246+
}
247+
},
248+
requestFrame = function() {
249+
return function(t) {
250+
return window.requestAnimationFrame(t)
251+
}
252+
}(),
253+
cancelFrame = function() {
254+
return function(t) {
255+
return window.cancelAnimationFrame(t)
256+
}
257+
}(),
258+
resetTriggers = function(e) {
259+
var t = e.__rt__,
260+
n = t.firstElementChild,
261+
r = t.lastElementChild,
262+
i = n.firstElementChild;
263+
r.scrollLeft = r.scrollWidth;
264+
r.scrollTop = r.scrollHeight;
265+
i.style.width = n.offsetWidth + 1 + "px";
266+
i.style.height = n.offsetHeight + 1 + "px";
267+
n.scrollLeft = n.scrollWidth;
268+
n.scrollTop = n.scrollHeight
269+
},
270+
checkTriggers = function(e) {
271+
return e.offsetWidth != e.__rl__.width || e.offsetHeight != e.__rl__.height
272+
},
273+
scrollListener = function(e) {
274+
var t = this;
275+
resetTriggers(this);
276+
if (this.__rRAF__) cancelFrame(this.__rRAF__);
277+
this.__rRAF__ = requestFrame(function() {
278+
if (checkTriggers(t)) {
279+
t.__rl__.width = t.offsetWidth;
280+
t.__rl__.height = t.offsetHeight;
281+
t.__rl__.forEach(function(n) {
282+
n.call(t, e)
283+
})
284+
}
285+
})
286+
},
287+
rafPolyFill = function() {
288+
var _af = 'AnimationFrame',
289+
_req = 'Request',
290+
_raf = 'request' + _af,
291+
_can = 'Cancel',
292+
_caf = 'cancel' + _af,
293+
expire = 0,
294+
vendors = ['moz', 'ms', 'o', 'webkit'],
295+
pre;
296+
297+
while (!window[_raf] && (pre = vendors.pop())) {
298+
window[_raf] = window[pre + _req + _af];
299+
window[_caf] = window[pre + _can + _af] || window[pre + _can + _req + _af];
300+
}
301+
302+
if (!window[_raf]) {
303+
window[_raf] = function(callback) {
304+
var current = +new Date,
305+
adjusted = 16 - (current - expire),
306+
delay = adjusted > 0 ? adjusted : 0;
307+
expire = current + delay;
308+
309+
return setTimeout(function() {
310+
callback(expire);
311+
}, delay);
312+
};
313+
window[_caf] = clearTimeout;
314+
}
315+
}
316+
}
317+
window.addResizeListener = function(t, n) {
318+
if (attachEvent) t.attachEvent("onresize", n);
319+
else {
320+
if (!t.__rt__) {
321+
if (getComputedStyle(t).position == "static") t.style.position = "relative";
322+
rafPolyFill();
323+
createStyles();
324+
t.__rl__ = {};
325+
t.__rl__ = [];
326+
(t.__rt__ = document.createElement("div")).className = "r-t";
327+
t.__rt__.innerHTML = '<div class="e-t"><div></div></div>' + '<div class="c-t"></div>';
328+
t.appendChild(t.__rt__);
329+
resetTriggers(t);
330+
t.addEventListener("scroll", scrollListener, true)
331+
}
332+
t.__rl__.push(n)
333+
}
334+
};
335+
window.removeResizeListener = function(t, n) {
336+
if (attachEvent) t.detachEvent("onresize", n);
337+
else {
338+
t.__rl__.splice(t.__rl__.indexOf(n), 1);
339+
if (!t.__rl__.length) {
340+
t.removeEventListener("scroll", scrollListener);
341+
t.__rt__ = !t.removeChild(t.__rt__)
342+
}
343+
}
344+
}
345+
})(jQuery, window, document);

0 commit comments

Comments
 (0)