UNPKG

camel-components

Version:
139 lines (125 loc) 3.95 kB
import React from 'react' import R from 'ramda' class AnimationWindow extends React.Component { componentWillMount() { let {frameStart, scenes, transitionSpeed} = this.props let framesTotal = 0 let elementIds = {} scenes.forEach((scene) => { if (typeof frameStart === 'string' && frameStart === scene.name) { frameStart = framesTotal } Object.keys(scene.elements).forEach((key) => {elementIds[key] = true}) framesTotal += scene.frames }) elementIds = Object.keys(elementIds) const defaultStyles = { position: 'absolute', display: 'flex', justifyContent: 'center', alignItems: 'center', backgroundPosition: 'center center', backgroundSize: 'contain', backgroundRepeat: 'no-repeat', opacity: 1, transition: `left ${transitionSpeed}ms ease,top ${transitionSpeed}ms ease, height ${transitionSpeed}ms ease, width ${transitionSpeed}ms ease, border ${transitionSpeed}ms ease, border-color ${transitionSpeed}ms ease, background-color ${transitionSpeed}ms ease, background-position ${transitionSpeed}ms ease, opacity ${transitionSpeed}ms ease` } this.setState({ frame: frameStart, framesTotal, defaultStyles, elementIds }) } componentDidMount() { if (this.props.animation) { this.setState({ timer: setInterval(() => { this.nextFrame() }, 200) }) } } shouldComponentUpdate(nextState) { if (this.state.frame === nextState.frame) return false return true } nextFrame() { const {stopOnEnd} = this.props const {frame, framesTotal, timer} = this.state const newFrame = (frame < framesTotal - 1) ? frame + 1 : 0 if (stopOnEnd && (newFrame === 0)) { clearInterval(timer) } else { this.setState({ frame: newFrame }) } } render () { const {frame, defaultStyles, elementIds} = this.state const {scenes, windowStyles} = this.props const getCurrentScene = (frame, scenes) => { let scene = 0 do { frame -= scenes[scene].frames if (frame < 0) return scene scene++ if (!scenes[scene]) return 0 // fallback preventing endless loop } while (true) } const currentScene = getCurrentScene(frame, scenes) const animationElement = (element, elementId) => { if (element) { const {content} = element return ( <div key={elementId} style={{...defaultStyles, ...element.style}}>{content ? content : null}</div> ) } } const aggregateElement = (scenes, currentScene, elementId) => { let style = {} let searchScene = currentScene do { let element = R.clone(scenes[searchScene].elements[elementId]) if (typeof element === 'undefined') element = true if (typeof element === 'object') { if (element.removeAfterScene && searchScene !== currentScene) { return false } if (element.styleUpdate) { style = {...element.styleUpdate, ...style} } else { style = {...element.style, ...style} } if (style.transition === 'default') { style.transition = defaultStyles.transition } if (!element.styleUpdate) { element.style = style return element } } else { if (!element) { return false } } searchScene-- } while (searchScene >= 0) return false } const animationElements = () => { return elementIds.map((elementId) => { return animationElement(aggregateElement(scenes, currentScene, elementId), elementId) }) } return ( <div className={`AnimationWindow scene${currentScene}`} style={windowStyles}> {animationElements()} </div> ) } } export { AnimationWindow }