Skip to content

Instantly share code, notes, and snippets.

@ArnaudValensi
Created July 1, 2016 09:59
Show Gist options
  • Save ArnaudValensi/eef95545cb8a47b5d54887f41edd3430 to your computer and use it in GitHub Desktop.
Save ArnaudValensi/eef95545cb8a47b5d54887f41edd3430 to your computer and use it in GitHub Desktop.
import React from 'react'
import ReactDOM from 'react-dom'
import classNames from 'classnames'
export default class ScrollEffect extends React.Component {
constructor () {
super()
this.state = {
animated: false
}
window.addEventListener('scroll', throttle(200, this.handleScroll.bind(this)))
}
componentWillUnmount = () => {
window.removeEventListener('scroll', this.handleScroll.bind(this))
}
singleAnimate = () => {
this.setState({
animated: true
})
/* callback */
setTimeout(() => {
this.props.callback()
}, this.props.duration * 1000)
}
queueAnimate = () => {
let element = ReactDOM.findDOMNode(this)
let checkClass = (el) => {
return el.className === this.props.queueClass
}
let number = 0
let setClass = (el) => {
el.style.visibility = 'hidden'
setTimeout(() => {
el.style.visibility = 'visible'
el.className = el.className + ' animated ' + this.props.animate
}, number * (this.props.queueDuration * 1000))
number++
}
let findClass = (element) => {
Array.prototype.forEach.call(element.childNodes, function (child) {
findClass(child)
if (checkClass(child)) {
setClass(child)
}
})
}
/* find queue classes */
findClass(element)
/* callback */
setTimeout(() => {
this.props.callback()
}, this.props.duration * 1000 * number)
}
handleScroll = (e) => {
if (!this.state.animated) {
let element = ReactDOM.findDOMNode(this)
let elementPositionY = element.getBoundingClientRect().top + document.body.scrollTop
let scrollPositionY = window.scrollY
let windowHeight = window.innerHeight
if (scrollPositionY + windowHeight / 2 >= elementPositionY + this.props.offset * 1) {
this.setState({
animated: true
})
this.props.queueClass == '' && this.singleAnimate()
this.props.queueClass !== '' && this.queueAnimate()
}
}
}
render = () => {
const { props, state } = this
let classes = classNames({
'animated': true,
[props.animate]: state.animated && props.queueClass === ''
})
classes += ' ' + props.className
let style = state.animated ? {} : {
visibility: 'hidden'
}
if (props.duration !== '') {
style.WebkitAnimationDuration = props.duration + 's'
style.animationDuration = props.duration + 's'
}
return <div className={classes} style={style}>{props.children}</div>
}
}
ScrollEffect.defaultProps = {
animate: 'fadeInUp',
offset: 0,
className: '',
duration: 1,
queueDuration: 1,
queueClass: '',
callback: () => {}
}
let throttle = (delay, callback) => {
let previousCall = new Date().getTime()
return () => {
let time = new Date().getTime()
if ((time - previousCall) >= delay) {
previousCall = time
callback.apply(null, arguments)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment