Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active April 1, 2020 17:11
Show Gist options
  • Save gaearon/02c4905ee6981fcab9f6 to your computer and use it in GitHub Desktop.
Save gaearon/02c4905ee6981fcab9f6 to your computer and use it in GitHub Desktop.
Scrolljack.jsx
'use strict';
var React = require('react'),
PureRenderMixin = require('../mixins/PureRenderMixin'),
getSupportedTransformProperty = require('../utils/getSupportedTransformProperty'),
{ PropTypes, Children } = React;
const transformProperty = getSupportedTransformProperty();
const styles = {
root: {
width: '100%',
height: '100%'
},
child(index, props) {
const translateY = index > (props.activeIndex - 1) ? '0' : '-100%';
return Object.assign({
width: '100%'
}, !props.disabled && {
position: 'fixed',
transition: `${transformProperty.css} ${props.transitionDuration}ms cubic-bezier(.175, .885, .32, 1)`,
willChange: `${transformProperty.css}`,
[transformProperty.js]: `translate3d(0, ${translateY}, 0)`,
});
}
};
var Scrolljack = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
disabled: PropTypes.bool,
activeIndex: PropTypes.number.isRequired,
requestActiveIndexChange: PropTypes.func.isRequired,
navigation: PropTypes.element,
transitionDuration: PropTypes.number,
extraDisableScrollDuration: PropTypes.number
},
componentWillUnmount() {
clearTimeout(this.timeout);
},
render() {
const { disabled, navigation } = this.props;
return (
<div style={styles.root}
onWheel={this.handleWheel}>
{this.renderChildren()}
{!disabled && navigation}
</div>
);
},
renderChildren() {
var wrappers = [];
Children.forEach(this.props.children, (child, index) =>
wrappers.push(
<div key={index} style={styles.child(index, this.props)}>
{child}
</div>
)
);
if (!this.props.disabled) {
// To avoid calculating z-index, just stack them
wrappers.reverse();
}
return wrappers;
},
handleWheel(e) {
if (this.props.disabled) {
return;
}
e.preventDefault();
const { activeIndex } = this.props;
const { deltaY } = e;
if (deltaY < 0 && activeIndex > 0) {
this.requestChangeAfterCurrentTransition(activeIndex - 1);
} else if (deltaY > 0) {
this.requestChangeAfterCurrentTransition(activeIndex + 1);
}
},
requestChangeAfterCurrentTransition(index) {
if (this.isAnimating) {
return;
}
const { transitionDuration, extraDisableScrollDuration } = this.props;
const disableScrollDuration = transitionDuration + extraDisableScrollDuration;
this.isAnimating = true;
this.timeout = setTimeout(() => {
this.isAnimating = false;
}, disableScrollDuration);
this.props.requestActiveIndexChange(index);
}
});
module.exports = Scrolljack;
//
// getSupportedTranslateProperty.js
//
'use strict';
var TRANSFORM_VARIANTS = {
'WebkitTransform': '-webkit-transform',
'transform': 'transform',
};
function test() {
var testEl = document.createElement('div'),
style = testEl.style;
for (let [jsProp, cssProp] of Object.entries(TRANSFORM_VARIANTS)) {
style.cssText = `${cssProp}: translate3d(0, 0, 0)`;
if (style[jsProp] && style[jsProp].length) {
return {
js: jsProp,
css: cssProp
};
}
}
}
var property;
function getSupportedTransformProperty() {
if (!property) {
property = test();
}
return property;
}
module.exports = getSupportedTransformProperty;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment