UNPKG

labo-components

Version:
213 lines (181 loc) 5.1 kB
import PlayerAPI from '../PlayerAPI'; import IDUtil from '../../../util/IDUtil'; //https://developers.google.com/youtube/iframe_api_reference //https://tutorialzine.com/2015/08/how-to-control-youtubes-video-player-with-javascript class YouTubePlayer extends React.Component { constructor(props) { super(props); this.state = { player : null } } componentDidMount() { if(!document.getElementById('youtubeiframeapi')) { const tag = document.createElement('script'); tag.id = 'youtubeiframeapi'; tag.src = "https://www.youtube.com/iframe_api"; const firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); window.onYouTubeIframeAPIReady = this.onYouTubeIframeAPIReady.bind(this); } else { this.onYouTubeIframeAPIReady(); } } componentDidUpdate() { if(!this.state.player) { this.onYouTubeIframeAPIReady(); } } shouldComponentUpdate(nextProps, nextState) { if(nextProps.mediaObject.assetId == this.props.mediaObject.assetId) { return false } return true } componentDidUpdate() { console.debug('make sure the new media object ' + this.props.mediaObject.assetId + ' is loaded') } componentWillUnmount() { if(this.state.player) { this.state.player.destroy(); clearInterval(this.updateInterval); } } //TODO add support for playing a certain fragment on start onYouTubeIframeAPIReady() { let loaded = false; try { if (YT && YT.loaded == 1) { loaded = true; } } catch(e) { loaded = false; } if(loaded) { const player = new YT.Player('video_player__' + this.props.mediaObject.id, { height: '320', width: '480', videoId: this.getVideoId(),//M7lc1UVf-VE events: { 'onReady': this.onPlayerReady.bind(this), 'onStateChange': this.onPlayerStateChange.bind(this) } }); this.setState({player: player}); } else { console.debug('got here too soon'); } } getVideoId() { if(this.props.mediaObject) { if(this.props.mediaObject.url.indexOf('youtu.be') != -1) { let tmp = this.props.mediaObject.url.split('/'); return tmp[tmp.length -1].substring(0, 11); // make sure to cut of at the right point } else if(this.props.mediaObject.url.indexOf('v=') != -1) { const vidIndex = this.props.mediaObject.url.indexOf('v=') + 2 return this.props.mediaObject.url.substring( vidIndex, vidIndex + 11 // make sure to cut of at the right point ); } } return null; } onPlayerReady(event) { if(this.props.onPlayerReady) { //send back the api to the owning component this.props.onPlayerReady(new YouTubeAPI(this.state.player)); } //the youtube iframe API does not have an equivalent of onTime or onProgress. this.videotime = 0; this.updateInterval = setInterval(this.updateTime.bind(this), 100); } updateTime() { const oldTime = this.videotime; if(this.state.player && this.state.player.getCurrentTime) { this.videotime = this.state.player.getCurrentTime(); } if(this.videotime !== oldTime) { this.onProgress(this.videotime); } } onProgress(currentTime) { if(this.props.eventCallbacks) { this.props.eventCallbacks.playProgress(currentTime); } } onPlayerStateChange(event) { if(this.props.eventCallbacks) { switch (event.data) { case YT.PlayerState.BUFFERING : this.props.eventCallbacks.loadProgress(event);break; case YT.PlayerState.PLAYING : this.props.eventCallbacks.onPlay(event);break; case YT.PlayerState.PAUSED : this.props.eventCallbacks.onPause(event);break; case YT.PlayerState.ENDED : this.props.eventCallbacks.onFinish(event);break; } } } render() { return ( <div id={'video_player__' + this.props.mediaObject.id} className={IDUtil.cssClassName('youtube-player')}/> ) } } class YouTubeAPI extends PlayerAPI { constructor(playerAPI) { super(playerAPI); this.lastVolume = -1; } /* ------------ Implemented API calls ------------- */ play() { this.playerAPI.playVideo(); } pause() { this.playerAPI.pauseVideo(); } seek(secs) { this.playerAPI.seekTo(secs); } getPosition(callback=null) { if(!callback) { return this.playerAPI.getCurrentTime() } callback(this.playerAPI.getCurrentTime()); } getDuration(callback=null) { if(!callback) { return this.playerAPI.getDuration() } callback(this.playerAPI.getDuration()); } isPaused(callback=null) { if(!callback) { return this.playerAPI.getPlayerState() == 2 } callback(this.playerAPI.getPlayerState() == 2); } setVolume(volume) { //range between 0-1 this.playerAPI.setVolume(volume * 100); //range between 0-100 } getVolume() { if(volume !== 0) { this.lastVolume = volume; } return this.playerAPI.getVolume() } getLastVolume() { return this.lastVolume } setMute(isMuted) { if(this.playerAPI.isMuted()) { this.playerAPI.mute(); } else { this.playerAPI.unMute() } if(this.isMuted()) { this.lastVolume = this.playerAPI.getVolume(); } } isMuted() { return this.playerAPI.isMuted() } } export default YouTubePlayer;