Do you have any tips on smoothing out the scrolling animation for a React component with a simple parallax effect? I tried using requestAnimationFrame()
in vanilla JS, but it doesn't seem to work well within the React component's rendering cycle.
Also, is there a way to prevent changing the state of the element once it's out of view?
Check out my code implementation below:
const Parallax = React.createClass({
getInitialState: function () {
return {
top: 0,
opacity: 1
};
},
parallax: function(event) {
const scrollTop = window.pageYOffset;
const elementHeight = this.splash.clientHeight;
this.setState({ top: scrollTop * .7 + 'px' });
this.setState({ opacity: (elementHeight - scrollTop) / elementHeight });
},
componentDidMount: function() {
window.addEventListener('scroll', this.parallax);
},
componentWillUnmount: function() {
window.removeEventListener('scroll', this.parallax);
},
render: function() {
const splashStyle = {
transform: 'translateY(' + this.state.top +')',
opacity: this.state.opacity
};
return (
<div className="splash"
ref={ domElement => { this.splash = domElement; }}>
<div className="splash__wrapper " style={ splashStyle }>
<p>LONG CONTENT</p>
</div>
</div>
);
}
});
ReactDOM.render(
<Parallax />,
document.getElementById('container')
);
.splash {
position: relative;
width: 100vw;
max-width: 100%;
height: 100vh;
min-height: 500px;
background: url(https://facebook.github.io/react/img/logo_og.png) no-repeat 10% 60%;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
.splash__wrapper {
position: absolute;
color: #fff;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
transition: 0s transform;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Update:
I managed to limit state changes only when the Splash component is visible at the top of the page. However, I still can't improve the scroll performance.
if (scrollTop < elementHeight) {
this.setState({ top: scrollTop * .7 + 'px' });
this.setState({ opacity: (elementHeight - scrollTop) / elementHeight });
}