labo-components
Version:
213 lines (181 loc) • 5.1 kB
JSX
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;