Skip to content

Instantly share code, notes, and snippets.

@egstad
Created May 20, 2019 18:58
Show Gist options
  • Save egstad/f6791ce6eb1175fd1f6a89850757048d to your computer and use it in GitHub Desktop.
Save egstad/f6791ce6eb1175fd1f6a89850757048d to your computer and use it in GitHub Desktop.
Animation
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