react-video-scroll-ssr
Version:
A React component to seek or control the video frame rate on scroll.
194 lines (154 loc) • 6.61 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var PropTypes = _interopDefault(require('prop-types'));
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var rAF = typeof window !== 'undefined' ? window.requestAnimationFrame : function () {};
var VideoScroll = function (_React$Component) {
inherits(VideoScroll, _React$Component);
function VideoScroll() {
var _temp, _this, _ret;
classCallCheck(this, VideoScroll);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.videoRef = React.createRef(), _this.divWrapperRef = React.createRef(), _this.seek = function () {
// Start the video from beginning
var currentFrame = 0;
if (typeof _this.props.onLoad === 'function') {
// Invoke the callback and apply any necessary styles or adjustments
_this.props.onLoad({
wrapperEl: _this.divWrapperRef.current,
videoEl: _this.videoRef.current,
duration: _this.videoRef.current.duration,
playbackRate: _this.props.playbackRate
});
}
var startOnScroll = function startOnScroll() {
// User defined function to set the current frame and seek the video on scroll
if (_this.props.setCurrentFrame && typeof _this.props.setCurrentFrame === 'function') {
currentFrame = _this.props.setCurrentFrame({
playbackRate: _this.props.playbackRate,
duration: _this.videoRef.current.duration
});
} else {
var offset = _this.props.horizontalScroll ? window.pageXOffset : window.pageYOffset;
currentFrame = offset / _this.props.playbackRate;
}
// Set the current frame when scroll along x or y axis
_this.videoRef.current.currentTime = currentFrame;
// Do some extra stuff here
if (typeof _this.props.onScroll === 'function') {
_this.props.onScroll({
wrapperEl: _this.divWrapperRef.current,
videoEl: _this.videoRef.current,
currentFrame: currentFrame,
duration: _this.videoRef.current.duration,
playbackRate: _this.props.playbackRate
});
}
rAF(startOnScroll);
};
rAF(startOnScroll);
}, _this.attachRefToVideoEl = function () {
// For tracking the number of <video> elements which are children of <VideoScroll> component
var count = 0;
return React.Children.map(_this.props.children, function (child, i) {
if (child.type === 'video') {
count += 1;
// To seek more than one video, wrap the other video element inside an another VideoScroll component
if (count > 1) {
var PROD_ERR = '<VideoScroll> component expected only one <video> element as its children';
throw new Error(process.env.NODE_ENV !== 'production' ? PROD_ERR + ' but received more than one <video> element. To seek both the videos, wrap the other video element inside another <VideoScroll> component.' : PROD_ERR + '.');
} else if (count === 1) {
return React.cloneElement(child, { key: i, ref: _this.videoRef });
}
}
return React.cloneElement(child, { key: i });
});
}, _temp), possibleConstructorReturn(_this, _ret);
}
// TODO: https://github.com/facebook/flow/pull/5920
// $FlowFixMe
// TODO: https://github.com/facebook/flow/pull/5920
// $FlowFixMe
VideoScroll.prototype.componentDidMount = function componentDidMount() {
this.videoRef.current.addEventListener('loadedmetadata', this.seek);
};
VideoScroll.prototype.componentWillUnmount = function componentWillUnmount() {
this.videoRef.current.removeEventListener('loadedmetadata', this.seek);
};
VideoScroll.prototype.render = function render() {
var _props = this.props,
children = _props.children,
playbackRate = _props.playbackRate,
setCurrentFrame = _props.setCurrentFrame,
horizontalScroll = _props.horizontalScroll,
onScroll = _props.onScroll,
onLoad = _props.onLoad,
rest = objectWithoutProperties(_props, ['children', 'playbackRate', 'setCurrentFrame', 'horizontalScroll', 'onScroll', 'onLoad']);
return React.createElement(
'div',
_extends({ ref: this.divWrapperRef }, rest),
this.attachRefToVideoEl()
);
};
return VideoScroll;
}(React.Component);
VideoScroll.defaultProps = {
playbackRate: 10,
horizontalScroll: false
};
process.env.NODE_ENV !== "production" ? VideoScroll.propTypes = {
playbackRate: PropTypes.number,
horizontalScroll: PropTypes.bool,
onScroll: PropTypes.func,
onLoad: PropTypes.func,
setCurrentFrame: PropTypes.func
} : void 0;
exports.VideoScroll = VideoScroll;