Skip to content

Instantly share code, notes, and snippets.

@adjohu
Created March 20, 2016 21:19
Show Gist options
  • Save adjohu/995b7bce5295d6829c2e to your computer and use it in GitHub Desktop.
Save adjohu/995b7bce5295d6829c2e to your computer and use it in GitHub Desktop.
react-motion-parallax
export {default as Parallax} from './parallax.js';
export {default as default} from './parallax.js';
export {Layer as Layer} from './layer.js';
import React, {PropTypes} from 'react';
import styles from './layer.scss';
class Layer extends React.Component {
static defaultProps = {
xOffset: 0,
depth: 0
};
getXTranslation() {
const {xOffset, depth} = this.props;
return -1 * xOffset * depth;
}
getStyle() {
const {xOffset} = this.props;
return {
transform: `translateX(${this.getXTranslation()}px)`
}
}
render() {
const {children, ...props} = this.props;
return (
<div
{...props}
className={styles.base}
style={this.getStyle()}
>
{children}
</div>
)
}
}
export default Layer;
.base {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
import React, {PropTypes} from 'react';
import Parallax from './parallax';
//import styles from './mouseMoveParallax.scss';
class MouseMoveParallax extends React.Component {
static defaultProps = {
};
constructor() {
super(...arguments);
this.state = {
mouseX: 0,
mouseY: 0,
centerX: 0,
centerY: 0
}
}
componentDidMount() {
window.addEventListener('touchmove', ::this.handleTouchMove);
window.addEventListener('mousemove', ::this.handleMouseMove);
window.addEventListener('resize', ::this.handleResize);
this.handleResize();
}
handleTouchMove(e) {
e.preventDefault();
this.handleMouseMove(e.touches[0]);
}
handleResize() {
this.setState({
centerX: window.innerWidth / 2,
centerY: window.innerHeight / 2
})
}
handleMouseMove({pageX: mouseX, pageY: mouseY}) {
this.setState({
mouseX, mouseY
});
}
getMouseOffsetFromCenter() {
const {centerX, centerY, mouseX, mouseY} = this.state;
return {
x: mouseOffset(centerX, mouseX),
y: mouseOffset(centerY, mouseY)
};
}
render() {
const {children, ...props} = this.props;
const mouseOffset = this.getMouseOffsetFromCenter();
return (
// <div {...props} className={styles.base}>
<Parallax {...props} xOffset={mouseOffset.x}>
{children}
</Parallax>
)
}
}
function mouseOffset(center, mousePos) {
const offset = mousePos - center;
const root = Math.sqrt(Math.abs(offset));
if (offset < 0) return -1 * root;
return root;
}
export default MouseMoveParallax;
import React, {PropTypes, cloneElement} from 'react';
import {StaggeredMotion, spring} from 'react-motion';
import styles from './parallax.scss';
export class Parallax extends React.Component {
static defaultProps = {
xOffset: 0
};
getDefaultStyles() {
return React.Children.map(this.props.children, child => ({
xOffset: 0
}));
}
getStyles(prevInterpolatedStyles) {
const {xOffset} = this.props;
return prevInterpolatedStyles.map((_, i) => {
return i === 0
? {xOffset: spring(xOffset)}
: {xOffset: spring(prevInterpolatedStyles[i-1].xOffset)}
});
}
renderLayers(interpolatingStyles = []) {
const {children} = this.props;
return (
<div>
{interpolatingStyles.map(({xOffset}, i) => {
return cloneElement(children[i], { xOffset, key: i });
})}
</div>
);
}
render() {
const {children, ...props} = this.props;
return (
<div {...props} className={styles.base}>
<StaggeredMotion
defaultStyles={::this.getDefaultStyles()}
styles={::this.getStyles}
>{::this.renderLayers}</StaggeredMotion>
</div>
)
}
}
export {Layer} from './layer';
export default Parallax;
.base {
position: relative;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment