simple-aos
Version:
Simple AOS - Animate on scroll library
236 lines (202 loc) • 5.92 kB
JavaScript
/**
* *******************************************************
* AOS (Animate on scroll) - wowjs alternative
* made to animate elements on scroll in both directions
* *******************************************************
*/
import './../sass/aos.scss';
// Modules & helpers
import throttle from 'lodash.throttle';
import debounce from 'lodash.debounce';
import observer from './libs/observer';
import detect from './helpers/detector';
import handleScroll from './helpers/handleScroll';
import prepare from './helpers/prepare';
import elements from './helpers/elements';
/**
* Private variables
*/
let $aosElements = [];
let initialized = false;
/**
* Default options
*/
let options = {
offset: 120,
delay: 0,
easing: 'ease',
duration: 400,
disable: false,
once: false,
mirror: false,
anchorPlacement: 'top-bottom',
startEvent: 'DOMContentLoaded',
animatedClassName: 'aos-animate',
initClassName: 'aos-init',
useClassNames: false,
disableMutationObserver: false,
throttleDelay: 99,
debounceDelay: 50
};
// Detect not supported browsers (<=IE9)
// http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
const isBrowserNotSupported = () => document.all && !window.atob;
const initializeScroll = () => {
// Extend elements objects in $aosElements with their positions
$aosElements = prepare($aosElements, options);
// Perform scroll event, to refresh view and show/hide elements
handleScroll($aosElements);
/**
* Handle scroll event to animate elements on scroll
*/
window.addEventListener(
'scroll',
throttle(() => {
handleScroll($aosElements, options.once);
}, options.throttleDelay),
{ passive: true }
);
return $aosElements;
};
/**
* Refresh AOS
*/
const refresh = (initialize = false) => {
// Allow refresh only when it was first initialized on startEvent
initialize && (initialized = true) && initializeScroll();
};
/**
* Hard refresh
* create array with new elements and trigger refresh
*/
const refreshHard = () => {
$aosElements = elements();
if (isDisabled(options.disable) || isBrowserNotSupported()) {
return disable();
}
refresh();
};
/**
* Disable AOS
* Remove all attributes to reset applied styles
*/
const disable = () => {
$aosElements.forEach(el => {
el.node.removeAttribute('data-aos');
el.node.removeAttribute('data-aos-easing');
el.node.removeAttribute('data-aos-duration');
el.node.removeAttribute('data-aos-delay');
if (options.initClassName) {
el.node.classList.remove(options.initClassName);
}
if (options.animatedClassName) {
el.node.classList.remove(options.animatedClassName);
}
});
};
/**
* Check if AOS should be disabled based on provided setting
*/
const isDisabled = optionDisable => {
return (
optionDisable === true ||
(optionDisable === 'mobile' && detect.mobile()) ||
(optionDisable === 'phone' && detect.phone()) ||
(optionDisable === 'tablet' && detect.tablet()) ||
(typeof optionDisable === 'function' && optionDisable() === true)
);
};
/**
* Initializing AOS
* - Create options merging defaults with user defined options
* - Set attributes on <body> as global setting - css relies on it
* - Attach preparing elements to options.startEvent,
* window resize and orientation change
* - Attach function that handle scroll and everything connected to it
* to window scroll event and fire once document is ready to set initial state
*/
const init = settings => {
options = Object.assign(options, settings);
// Create initial array with elements -> to be fullfilled later with prepare()
$aosElements = elements();
// Detect not supported browsers (<=IE9)
// http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
const browserNotSupported = document.all && !window.atob;
/**
* Disable mutation observing if not supported
*/
if (!options.disableMutationObserver && !observer.isSupported()) {
console.info(`
aos: MutationObserver is not supported on this browser,
code mutations observing has been disabled.
You may have to call "refreshHard()" by yourself.
`);
options.disableMutationObserver = true;
}
/**
* Observe [aos] elements
* If something is loaded by AJAX
* it'll refresh plugin automatically
*/
if (!options.disableMutationObserver) {
observer.ready('[data-aos]', refreshHard);
}
/**
* Don't init plugin if option `disable` is set
* or when browser is not supported
*/
if (isDisabled(options.disable) || isBrowserNotSupported()) {
return disable();
}
/**
* Set global settings on body, based on options
* so CSS can use it
*/
document
.querySelector('body')
.setAttribute('data-aos-easing', options.easing);
document
.querySelector('body')
.setAttribute('data-aos-duration', options.duration);
document.querySelector('body').setAttribute('data-aos-delay', options.delay);
/**
* Handle initializing
*/
if (['DOMContentLoaded', 'load'].indexOf(options.startEvent) === -1) {
// Listen to options.startEvent and initialize AOS
document.addEventListener(options.startEvent, () => {
refresh(true);
});
} else {
window.addEventListener('load', () => {
refresh(true);
});
}
if (
options.startEvent === 'DOMContentLoaded' &&
['complete', 'interactive'].indexOf(document.readyState) > -1
) {
// Initialize AOS if default startEvent was already fired
refresh(true);
}
/**
* Refresh plugin on window resize or orientation change
*/
window.addEventListener(
'resize',
debounce(refresh, options.debounceDelay, true)
);
window.addEventListener(
'orientationchange',
debounce(refresh, options.debounceDelay, true)
);
return $aosElements;
};
/**
* Export Public API
*/
export default {
init,
refresh,
refreshHard
};