Created
May 20, 2019 18:58
-
-
Save egstad/f6791ce6eb1175fd1f6a89850757048d to your computer and use it in GitHub Desktop.
Animation
This file contains hidden or 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
import dom from "./dom" | |
import utils from "./utils" | |
/* ========================================================================== | |
ANIMATE | |
========================================================================== | |
• When ".js-animate" elements are in view, ".is-active" class is added. | |
• Intersection Observer for modern browsers | |
• Scroll event fallback for browsers that don't support Intersection Ob. | |
========================================================================== */ | |
const animate = { | |
init() { | |
this.elements = (process.client) ? document.querySelectorAll(dom.animateClass) : '' | |
if (process.client) { | |
if ("IntersectionObserver" in window) { | |
this.observeInit() | |
this.options = { | |
threshold: 0 | |
} | |
} else { | |
this.scrollInit() | |
} | |
} | |
}, | |
destroy() { | |
if (process.client && this.elements.length) { | |
if ("IntersectionObserver" in window) { | |
this.observeDestroy() | |
} else { | |
this.scrollDestroy() | |
} | |
} | |
}, | |
observeInit() { | |
this.observer = new IntersectionObserver((items) => { | |
items.forEach(item => { | |
if (item.isIntersecting) { | |
// in view | |
item.target.classList.add("is-active") | |
} else { | |
// out of view | |
item.target.classList.remove("is-active") | |
} | |
}) | |
}, this.options) | |
this.elements.forEach(item => { | |
this.observer.observe(item) | |
}) | |
}, | |
observeDestroy() { | |
this.elements.forEach(item => { | |
this.observer.unobserve(item) | |
}) | |
this.elements = [] | |
}, | |
scrollInit() { | |
// bind this to the handler | |
this.scrollHandler = this.scrollHandler.bind(this) | |
this.ticking = false | |
// setup events | |
window.addEventListener("scroll", this.scrollHandler, { | |
passive: true | |
}) | |
window.addEventListener("resize", this.scrollHandler, { | |
passive: true | |
}) | |
// activate those in view now | |
this.scrollHandler() | |
}, | |
scrollDestroy() { | |
// destroy events | |
window.removeEventListener("scroll", this.scrollHandler, { | |
passive: true | |
}) | |
window.removeEventListener("resize", this.scrollHandler, { | |
passive: true | |
}) | |
// reset values | |
this.ticking = false | |
}, | |
scrollHandler(e) { | |
if (!this.ticking) { | |
window.requestAnimationFrame(() => { | |
// set state for each element | |
this.elements.forEach(item => { | |
this.checkPosition(item) | |
}) | |
this.ticking = false | |
}) | |
this.ticking = true | |
} | |
}, | |
checkPosition(item) { | |
if (utils.isElementVisible(item)) { | |
item.classList.add("is-active") | |
} else { | |
item.classList.remove("is-active") | |
} | |
} | |
} | |
if (process.client) { | |
window.onAppReady((app) => { | |
animate.init() | |
// update on new page | |
window.$app.$on('route::before', () => { | |
animate.destroy() | |
}) | |
// update on new page | |
window.$app.$on('page::mounted', () => { | |
animate.init() | |
}) | |
}) | |
} | |
export default animate |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment