Last active
August 20, 2021 12:50
-
-
Save mikechau/5547c67d0dc2957e907d to your computer and use it in GitHub Desktop.
Revisions
-
mikechau revised this gist
Sep 24, 2015 . 1 changed file with 146 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,44 +1,54 @@ var React = require('react'); var cx = require('classnames'); var vjs = require('video.js'); var _forEach = require('lodash/collection/forEach'); var _debounce = require('lodash/function/debounce'); var _defaults = require('lodash/object/defaults'); var DEFAULT_HEIGHT = 800; var DEFAULT_WIDTH = 600; var DEFAULT_ASPECT_RATIO = (9 / 16); var DEFAULT_ADJUSTED_SIZE = 0; var DEFAULT_RESIZE_DEBOUNCE_TIME = 500; var DEFAULT_VIDEO_OPTIONS = { preload: 'auto', autoplay: true, controls: true }; function noop() {} var Video = React.createClass({ propTypes: { src: React.PropTypes.string.isRequired, height: React.PropTypes.number, width: React.PropTypes.number, endlessMode: React.PropTypes.bool, options: React.PropTypes.object, onReady: React.PropTypes.func, eventListeners: React.PropTypes.object, resize: React.PropTypes.bool, resizeOptions: React.PropTypes.shape({ aspectRatio: React.PropTypes.number, shortWindowVideoHeightAdjustment: React.PropTypes.number, defaultVideoWidthAdjustment: React.PropTypes.number, debounceTime: React.PropTypes.number }), vjsDefaultSkin: React.PropTypes.bool, vjsBigPlayCentered: React.PropTypes.bool, children: React.PropTypes.element, dispose: React.PropTypes.bool, onNextVideo: React.PropTypes.func }, getDefaultProps: function() { return { endlessMode: false, options: DEFAULT_VIDEO_OPTIONS, onReady: noop, eventListeners: {}, resize: false, resizeOptions: {}, vjsDefaultSkin: true, vjsBigPlayCentered: true, onNextVideo: noop @@ -50,29 +60,36 @@ var Video = React.createClass({ }, componentWillReceiveProps: function(nextProps) { var isEndless = this.props.endlessMode; var willBeEndless = nextProps.endlessMode; if (isEndless !== willBeEndless) { if (willBeEndless) { this.addEndlessMode(); } else { this.removeEndlessMode(); } } var isResizable = this.props.resize; var willBeResizeable = nextProps.resize; if (isResizable !== willBeResizeable) { if (willBeResizeable) { this.addResizeEventListener(); } else { this.removeResizeEventListener(); } } var currentSrc = this.props.src; var newSrc = nextProps.src; if (currentSrc !== newSrc) { this.setVideoPlayerSrc(newSrc); } else if (isEndless === willBeEndless) { this.restartVideo(); } }, shouldComponentUpdate: function() { @@ -83,17 +100,58 @@ var Video = React.createClass({ this.unmountVideoPlayer(); }, getVideoPlayer: function() { return this._player; }, getVideoPlayerEl: function() { return React.findDOMNode(this.refs.videoPlayer); }, getVideoPlayerOptions: function() { return _defaults( {}, this.props.options, { height: this.props.resize ? 'auto' : (this.props.height || DEFAULT_HEIGHT), width: this.props.resize ? 'auto' : (this.props.width || DEFAULT_WIDTH) }, DEFAULT_VIDEO_OPTIONS); }, getVideoResizeOptions: function() { return _defaults({}, this.props.resizeOptions, { aspectRatio: DEFAULT_ASPECT_RATIO, shortWindowVideoHeightAdjustment: DEFAULT_ADJUSTED_SIZE, defaultVideoWidthAdjustment: DEFAULT_ADJUSTED_SIZE, debounceTime: DEFAULT_RESIZE_DEBOUNCE_TIME }); }, getResizedVideoPlayerMeasurements: function() { var resizeOptions = this.getVideoResizeOptions(); var aspectRatio = resizeOptions.aspectRatio; var defaultVideoWidthAdjustment = resizeOptions.defaultVideoWidthAdjustment; var winHeight = this._windowHeight(); var baseWidth = this._videoElementWidth(); var vidWidth = baseWidth - defaultVideoWidthAdjustment; var vidHeight = vidWidth * aspectRatio; if (winHeight < vidHeight) { var shortWindowVideoHeightAdjustment = resizeOptions.shortWindowVideoHeightAdjustment; vidHeight = winHeight - shortWindowVideoHeightAdjustment; } return { width: vidWidth, height: vidHeight }; }, setVideoPlayerSrc: function(src) { this._player.src(src); }, mountVideoPlayer: function() { var src = this.props.src; var options = this.getVideoPlayerOptions(); @@ -104,25 +162,23 @@ var Video = React.createClass({ player.ready(this.handleVideoPlayerReady); _forEach(this.props.eventListeners, function(val, key) { player.on(key, val); }); player.src(src); if (this.props.endlessMode) { this.addEndlessMode(); } }, unmountVideoPlayer: function() { this.removeResizeEventListener(); this._player.dispose(); }, addEndlessMode: function() { var player = this._player; player.on('ended', this.handleNextVideo); @@ -132,37 +188,62 @@ var Video = React.createClass({ } }, addResizeEventListener: function() { var debounceTime = this.getVideoResizeOptions().debounceTime; this._handleVideoPlayerResize = _debounce(this.handleVideoPlayerResize, debounceTime); window.addEventListener('resize', this._handleVideoPlayerResize); }, removeEndlessMode: function() { var player = this._player; player.off('ended', this.handleNextVideo); }, removeResizeEventListener: function() { window.removeEventListener('resize', this._handleVideoPlayerResize); }, pauseVideo: function() { this._player.pause(); }, playVideo: function() { this._player.play(); }, restartVideo: function() { this._player.currentTime(0).play(); }, togglePauseVideo: function() { if (this._player.paused()) { this.playVideo(); } else { this.pauseVideo(); } }, handleVideoPlayerReady: function() { this .getVideoPlayerEl() .parentElement .removeAttribute('data-reactid'); if (this.props.resize) { this.handleVideoPlayerResize(); this.addResizeEventListener(); } this.props.onReady(); }, handleVideoPlayerResize: function() { var player = this._player; var videoMeasurements = this.getResizedVideoPlayerMeasurements(); player.dimensions(videoMeasurements.width, videoMeasurements.height); }, handleNextVideo: function() { @@ -176,6 +257,14 @@ var Video = React.createClass({ ); }, _windowHeight: function() { return window.innerHeight; }, _videoElementWidth: function() { return this.getVideoPlayerEl().parentElement.parentElement.offsetWidth; }, render: function() { var videoPlayerClasses = cx({ 'video-js': true, @@ -185,7 +274,7 @@ var Video = React.createClass({ return ( <video ref="videoPlayer" className={videoPlayerClasses}> {this.props.children || this.renderDefaultWarning()} </video> ); } -
mikechau created this gist
Jul 12, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,194 @@ var React = require('react'); var cx = require('classnames'); var vjs = require('video.js'); var _ = require('lodash'); var DEFAULT_HEIGHT = 800; var DEFAULT_WIDTH = 600; function noop() {} var Video = React.createClass({ propTypes: { src: React.PropTypes.string.isRequired, pause: React.PropTypes.bool, endless: React.PropTypes.bool, options: React.PropTypes.object, onReady: React.PropTypes.func, eventListeners: React.PropTypes.object, resize: React.PropTypes.shape({ aspectRatio: React.PropTypes.number.isRequired, shortWindowVideoHeightAdjustment: React.PropTypes.number.isRequired, defaultVideoWidthAdjustment: React.PropTypes.number.isRequired }), vjsDefaultSkin: React.PropTypes.bool, vjsBigPlayCentered: React.PropTypes.bool, warningComponent: React.PropTypes.element, dispose: React.PropTypes.bool, onNextVideo: React.PropTypes.func }, getDefaultProps: function() { return { pause: false, endless: false, options: { preload: 'auto', autoplay: true, controls: true }, onReady: noop, eventListeners: {}, vjsDefaultSkin: true, vjsBigPlayCentered: true, onNextVideo: noop }; }, componentDidMount: function() { this.mountVideoPlayer(); }, componentWillReceiveProps: function(nextProps) { var isPaused = this.props.pause; var willBePaused = nextProps.pause; if (isPaused !== willBePaused) { var player = this._player; if (willBePaused) { player.pause(); } else { player.play(); } } var isEndless = this.props.endless; var willBeEndless = nextProps.endless; if (isEndless !== willBeEndless) { if (willBeEndless) { this.attachEndlessMode(); } else { this.detachEndlessMode(); } } }, shouldComponentUpdate: function() { return false; }, componentWillUnmount: function() { this.unmountVideoPlayer(); }, getVideoPlayerEl: function() { return React.findDOMNode(this.refs.videoPlayer); }, getVideoPlayerOptions: function() { return _.defaults({}, this.props.options, { height: this.props.resize ? 'auto' : (this.props.options.height || DEFAULT_HEIGHT), width: this.props.resize ? 'auto' : (this.props.options.width || DEFAULT_WIDTH) }); }, mountVideoPlayer: function() { var src = this.props.src; var options = this.getVideoPlayerOptions(); this._player = vjs(this.getVideoPlayerEl(), options); var player = this._player; player.ready(this.handleVideoPlayerReady); _.forEach(this.props.eventListeners, function(val, key) { player.on(key, val); }); player.src(src); }, unmountVideoPlayer: function() { window.removeEventListener('resize', this._handleVideoPlayerResize); // _.forEach(this.props.eventListeners, function(val, key) { // this._player.off(key); // }); this._player.off(); this._player.dispose(); }, attachEndlessMode: function() { var player = this._player; player.on('ended', this.handleNextVideo); if (player.ended()) { this.handleNextVideo(); } }, detachEndlessMode: function() { var player = this._player; player.off('ended', this.handleNextVideo); }, handleVideoPlayerReady: function() { if (this.props.resize) { this.handleVideoPlayerResize(); this._handleVideoPlayerResize = _.debounce(this.handleVideoPlayerResize, 100); window.addEventListener('resize', this._handleVideoPlayerResize); } this.props.onReady(); }, handleVideoPlayerResize: function() { var player = this._player; var aspectRatio = this.props.resize.aspectRatio; var vWidth = this.getVideoPlayerEl().parentElement.parentElement.offsetWidth; var vHeight = vWidth * aspectRatio; var winHeight = window.innerHeight; var defaultVideoWidthAdjustment = this.props.resize.defaultVideoWidthAdjustment; // Ensures videojs fits to the users viewable screen. if (winHeight < vHeight) { var shortWindowVideoHeightAdjustment = this.props.resize.shortWindowVideoHeightAdjustment; vHeight = winHeight - shortWindowVideoHeightAdjustment; } player.width(vWidth - defaultVideoWidthAdjustment).height(vHeight); }, handleNextVideo: function() { this.props.onNextVideo(); }, renderDefaultWarning: function() { return ( <p className="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>. </p> ); }, render: function() { var videoPlayerClasses = cx({ 'video-js': true, 'vjs-default-skin': this.props.vjsDefaultSkin, 'vjs-big-play-centered': this.props.vjsBigPlayCentered }); return ( <video ref="videoPlayer" className={videoPlayerClasses}> {this.props.warningComponent || this.renderDefaultWarning()} </video> ); } }); module.exports = Video;