UNPKG

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
'use strict'; 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;