Last active
August 29, 2015 13:59
-
-
Save jtangelder/10842041 to your computer and use it in GitHub Desktop.
inview.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* triggers a callback when an element gets into the viewport | |
* uses a little bit of jQuery. elements auto receive the class `inview` | |
* | |
* the threshold parameter is on scale from 0 to 1 of the height. | |
* 0 means it triggers directly, 1 means it must be full visible | |
* | |
* @example | |
* // images needs to be 50% in view | |
* inview.register("img", .5, function(item, inview_state) { | |
* console.log(item, inview_state); | |
* }); | |
*/ | |
/** | |
* requires the frameEvents lib, makes the events run at 60fps | |
* https://github.com/jtangelder/frame-events | |
* make sure you also have a requestAnimationFrame polyfill included. | |
* see the github page of frame-events for a link | |
*/ | |
var frameEvents = require('./frame-events'); | |
var jQuery = require('jquery'); | |
// holds all registered inview elements | |
var inview_elements = []; | |
/** | |
* collects the reflow vars on scroll | |
* @returns {{scrollY: Number}} | |
*/ | |
function collectOnScrollData() { | |
return { | |
scrollY: window.scrollY, | |
winHeight: window.innerHeight | |
}; | |
} | |
/** | |
* raf handler | |
* @method inViewElements | |
* @param [ev] | |
* @param scrollData | |
*/ | |
function inViewElements(ev, scrollData) { | |
var item, i, inview, threshold, | |
scrollY = scrollData.scrollY, | |
win_height = scrollData.winHeight; | |
// now update the classes | |
for(i = 0; i < inview_elements.length; i++) { | |
item = inview_elements[i]; | |
// item must be already x% inview | |
threshold = (item.height * item.threshold); | |
inview = ( | |
(scrollY + (win_height - threshold) > item.top) && | |
(scrollY < item.top + item.height - threshold) | |
); | |
item.element.toggleClass('inview', inview); | |
if(item.callback) { | |
item.callback(inview, item, scrollData); | |
} | |
} | |
} | |
/** | |
* update positions and run inview check | |
* @method updateInViewElements | |
* @param [ev] | |
* @param [scrollData] | |
*/ | |
function updateInViewElements(ev, scrollData) { | |
var i, item; | |
// collect offset, this will cause one reflow | |
for(i = 0; i < inview_elements.length; i++) { | |
item = inview_elements[i]; | |
item.top = item.element.offset().top; | |
item.height = item.element.outerHeight(); | |
} | |
inViewElements(ev, scrollData || collectOnScrollData()); | |
} | |
/** | |
* update in the next animation frame | |
* @method rafUpdate | |
*/ | |
function rafUpdate() { | |
requestAnimationFrame(function() { | |
updateInViewElements(); | |
}); | |
} | |
frameEvents.on(window, "load", updateInViewElements, collectOnScrollData); | |
frameEvents.on(window, "resize", updateInViewElements, collectOnScrollData); | |
frameEvents.on(window, "scroll", inViewElements, collectOnScrollData); | |
rafUpdate(); | |
// make sure the offset and heights are correct, every x ms | |
setInterval(rafUpdate, 5000); | |
module.exports = { | |
/** | |
* register function to add new inview elements | |
* @method register | |
* @param elements | |
* @param threshold on scale from 0 to 1. 0 means it triggers directly, 1 means it must be full visible | |
* @param [callback] | |
*/ | |
register: function(elements, threshold, callback) { | |
jQuery(elements).each(function() { | |
var el = jQuery(this); | |
// attribute before the argument | |
threshold = parseFloat(el.data("inview-threshold")) || threshold; | |
inview_elements.push({ | |
element: el, | |
threshold: threshold, | |
callback: callback | |
}); | |
}); | |
}, | |
/** | |
* update all inview elements on the next animation frame | |
* @method update | |
*/ | |
update: rafUpdate | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment