Encapsulate the zoom brains inside ClicksVideo so there's an easier path toward multi-player.

This commit is contained in:
Ian Gulliver
2015-11-21 11:16:44 -08:00
parent 972da0ab50
commit 6bbf3b16ec
2 changed files with 110 additions and 74 deletions

View File

@@ -296,6 +296,12 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
overflow: scroll; overflow: scroll;
visibility: hidden;
}
.clicks-player-container-active {
visibility: visible;
} }
.clicks-player-crop { .clicks-player-crop {

View File

@@ -3,7 +3,6 @@ var Clicks = function(youTubeAPIKey, container, takeDocumentHashOwnership, track
this.container_ = container; this.container_ = container;
this.players_ = []; this.players_ = [];
this.activePlayer_ = null; this.activePlayer_ = null;
this.zoomLevel_ = 1.0;
this.delayedConfig_ = {}; this.delayedConfig_ = {};
this.buildUI_(); this.buildUI_();
@@ -38,13 +37,14 @@ Clicks.keyStrings = {
' ': '<space>', ' ': '<space>',
'\x1b': '<esc>', '\x1b': '<esc>',
}; };
Clicks.zoomLevels = [
1.0,
1.5, Clicks.createElementAndAppend = function(className, parentNode) {
2.0, var element = document.createElement('div');
2.5, element.className = className;
3.0, parentNode.appendChild(element);
]; return element;
};
Clicks.prototype.trackEvent_ = function(var_args) { Clicks.prototype.trackEvent_ = function(var_args) {
@@ -101,14 +101,6 @@ Clicks.prototype.takeDocumentHashOwnership = function() {
}; };
Clicks.prototype.createElementAndAppend_ = function(className, parentNode) {
var element = document.createElement('div');
element.className = className;
parentNode.appendChild(element);
return element;
};
Clicks.prototype.onAddVideoValueChanged_ = function(e) { Clicks.prototype.onAddVideoValueChanged_ = function(e) {
var value = e.target.textContent; var value = e.target.textContent;
@@ -138,32 +130,32 @@ Clicks.prototype.onAddVideoValueChanged_ = function(e) {
Clicks.prototype.buildUI_ = function() { Clicks.prototype.buildUI_ = function() {
this.container_.tabIndex = -1; this.container_.tabIndex = -1;
this.addVideo_ = this.createElementAndAppend_( this.addVideo_ = Clicks.createElementAndAppend(
'clicks-add-video clicks-add-video-active', this.container_); 'clicks-add-video clicks-add-video-active', this.container_);
var addVideoDialog = this.createElementAndAppend_( var addVideoDialog = Clicks.createElementAndAppend(
'clicks-add-video-dialog', this.addVideo_); 'clicks-add-video-dialog', this.addVideo_);
this.addVideoValue_ = this.createElementAndAppend_( this.addVideoValue_ = Clicks.createElementAndAppend(
'clicks-add-video-input', addVideoDialog); 'clicks-add-video-input', addVideoDialog);
this.addVideoValue_.contentEditable = true; this.addVideoValue_.contentEditable = true;
this.addVideoValue_.addEventListener('keypress', function(e) { e.stopPropagation(); }); this.addVideoValue_.addEventListener('keypress', function(e) { e.stopPropagation(); });
this.addVideoValue_.addEventListener('input', this.onAddVideoValueChanged_.bind(this)); this.addVideoValue_.addEventListener('input', this.onAddVideoValueChanged_.bind(this));
this.addVideoValue_.focus(); this.addVideoValue_.focus();
this.loading_ = this.createElementAndAppend_( this.loading_ = Clicks.createElementAndAppend(
'clicks-loading', this.container_); 'clicks-loading', this.container_);
this.controls_ = this.createElementAndAppend_( this.controls_ = Clicks.createElementAndAppend(
'clicks-controls', this.container_); 'clicks-controls', this.container_);
var infoArea = this.createElementAndAppend_( var infoArea = Clicks.createElementAndAppend(
'clicks-control-info-area', this.controls_); 'clicks-control-info-area', this.controls_);
this.title_ = this.createElementAndAppend_( this.title_ = Clicks.createElementAndAppend(
'clicks-title', infoArea); 'clicks-title', infoArea);
this.channel_ = this.createElementAndAppend_( this.channel_ = Clicks.createElementAndAppend(
'clicks-channel', infoArea); 'clicks-channel', infoArea);
this.currentTime_ = this.createElementAndAppend_( this.currentTime_ = Clicks.createElementAndAppend(
'clicks-current-time', infoArea); 'clicks-current-time', infoArea);
this.totalTime_ = this.createElementAndAppend_( this.totalTime_ = Clicks.createElementAndAppend(
'clicks-total-time', infoArea); 'clicks-total-time', infoArea);
this.buffering_ = document.createElement('img'); this.buffering_ = document.createElement('img');
@@ -331,7 +323,7 @@ Clicks.prototype.buildUI_ = function() {
]; ];
var selectArea = this.createElementAndAppend_( var selectArea = Clicks.createElementAndAppend(
'clicks-control-section-select-area', this.controls_); 'clicks-control-section-select-area', this.controls_);
this.sectionSelectors_ = {}; this.sectionSelectors_ = {};
@@ -339,7 +331,7 @@ Clicks.prototype.buildUI_ = function() {
for (var i = 0; i < controls.length; i++) { for (var i = 0; i < controls.length; i++) {
var section = controls[i]; var section = controls[i];
var sectionSelect = this.createElementAndAppend_( var sectionSelect = Clicks.createElementAndAppend(
'clicks-control-section-select', selectArea); 'clicks-control-section-select', selectArea);
sectionSelect.textContent = section.title; sectionSelect.textContent = section.title;
sectionSelect.addEventListener( sectionSelect.addEventListener(
@@ -347,7 +339,7 @@ Clicks.prototype.buildUI_ = function() {
this.sectionSelectors_[section.title] = sectionSelect; this.sectionSelectors_[section.title] = sectionSelect;
} }
var sectionArea = this.createElementAndAppend_( var sectionArea = Clicks.createElementAndAppend(
'clicks-control-section-area', this.controls_); 'clicks-control-section-area', this.controls_);
this.sections_ = {}; this.sections_ = {};
@@ -356,13 +348,13 @@ Clicks.prototype.buildUI_ = function() {
for (var i = 0; i < controls.length; i++) { for (var i = 0; i < controls.length; i++) {
var section = controls[i]; var section = controls[i];
var sectionNode = this.createElementAndAppend_( var sectionNode = Clicks.createElementAndAppend(
'clicks-control-section', sectionArea); 'clicks-control-section', sectionArea);
this.sections_[section.title] = sectionNode; this.sections_[section.title] = sectionNode;
for (var j = 0; j < section.buttons.length; j++) { for (var j = 0; j < section.buttons.length; j++) {
var buttons = section.buttons[j]; var buttons = section.buttons[j];
var row = this.createElementAndAppend_( var row = Clicks.createElementAndAppend(
'clicks-control-section-row', sectionNode); 'clicks-control-section-row', sectionNode);
for (var k = 0; k < buttons.length; k++) { for (var k = 0; k < buttons.length; k++) {
@@ -374,20 +366,11 @@ Clicks.prototype.buildUI_ = function() {
} }
} }
this.playersContainer_ = this.createElementAndAppend_( this.playersContainer_ = Clicks.createElementAndAppend(
'clicks-players-container', this.container_); 'clicks-players-container', this.container_);
var playerContainer = this.createElementAndAppend_(
'clicks-player-container', this.playersContainer_);
this.playerCrop_ = this.createElementAndAppend_(
'clicks-player-crop', playerContainer);
this.playerScale_ = this.createElementAndAppend_(
'clicks-player-scale', this.playerCrop_);
var playerOverlay = this.createElementAndAppend_(
'clicks-player-overlay', this.playerScale_);
this.activateControlSection_(controls[0].title); this.activateControlSection_(controls[0].title);
playerOverlay.addEventListener('click', this.showHideControls_.bind(this));
this.container_.addEventListener('click', this.showHideControls_.bind(this)); this.container_.addEventListener('click', this.showHideControls_.bind(this));
}; };
@@ -467,7 +450,7 @@ Clicks.prototype.getConfigString = function() {
var config = { var config = {
'ytid': this.activePlayer_.id, 'ytid': this.activePlayer_.id,
'rate': this.activePlayer_.getRate().realRate, 'rate': this.activePlayer_.getRate().realRate,
'zoom': this.zoomLevel_, 'zoom': this.activePlayer_.getZoomLevel(),
'muted': this.activePlayer_.player.isMuted() ? 1 : 0, 'muted': this.activePlayer_.player.isMuted() ? 1 : 0,
'time': this.activePlayer_.player.getCurrentTime(), 'time': this.activePlayer_.player.getCurrentTime(),
}; };
@@ -562,10 +545,7 @@ Clicks.prototype.updateControls_ = function(e) {
Clicks.prototype.addVideo = function(id) { Clicks.prototype.addVideo = function(id) {
console.log('Adding YouTube video ID:', id); console.log('Adding YouTube video ID:', id);
var playerNode = document.createElement('div'); new ClicksVideo(this.youTubeAPIKey_, id, this.playersContainer_, this.onVideoAdded_.bind(this));
playerNode.style.visibility = 'hidden';
this.playerScale_.appendChild(playerNode);
new ClicksVideo(this.youTubeAPIKey_, id, playerNode, this.onVideoAdded_.bind(this));
this.addVideo_.className = 'clicks-add-video'; this.addVideo_.className = 'clicks-add-video';
this.container_.focus(); this.container_.focus();
@@ -585,7 +565,7 @@ Clicks.prototype.onVideoAdded_ = function(player) {
this.activePlayer_.setRate(parseFloat(value)); this.activePlayer_.setRate(parseFloat(value));
break; break;
case 'zoom': case 'zoom':
this.zoomLevel_ = parseFloat(value); this.activePlayer_.zoom(parseFloat(value));
break; break;
case 'muted': case 'muted':
if (parseInt(value)) { if (parseInt(value)) {
@@ -599,7 +579,7 @@ Clicks.prototype.onVideoAdded_ = function(player) {
break; break;
} }
} }
this.resizePlayer_(player); this.activePlayer_.resize();
this.activePlayer_.player.unMute(); this.activePlayer_.player.unMute();
document.title = player.metadata.title; document.title = player.metadata.title;
@@ -630,7 +610,7 @@ Clicks.prototype.onVideoAdded_ = function(player) {
this.sections_['Markers'].appendChild(markerNode); this.sections_['Markers'].appendChild(markerNode);
} }
player.playerNode.style.visibility = 'visible'; player.unhide();
this.loading_.className = 'clicks-loading clicks-loading-complete'; this.loading_.className = 'clicks-loading clicks-loading-complete';
player.player.playVideo(); player.player.playVideo();
@@ -638,24 +618,9 @@ Clicks.prototype.onVideoAdded_ = function(player) {
}; };
Clicks.prototype.resizePlayer_ = function(player) {
var zoom = Math.min(
this.container_.clientWidth / player.videoRes[0],
this.container_.clientHeight / player.videoRes[1]);
zoom = Math.min(zoom * this.zoomLevel_, 1.0);
this.playerScale_.style.transform = [
'scale(' + zoom + ',' + zoom + ')',
].join(' ');
this.playerScale_.style.width = player.videoRes[0];
this.playerScale_.style.height = player.videoRes[1];
this.playerCrop_.style.width = Math.ceil(player.videoRes[0] * zoom);
this.playerCrop_.style.height = Math.ceil(player.videoRes[1] * zoom);
};
Clicks.prototype.onWindowResize_ = function(e) { Clicks.prototype.onWindowResize_ = function(e) {
for (var i = 0; i < this.players_.length; i++) { for (var i = 0; i < this.players_.length; i++) {
this.resizePlayer_(this.players_[i]); this.players_[i].resize();
} }
}; };
@@ -770,16 +735,12 @@ Clicks.prototype.onKeyPress_ = function(e) {
case '-': case '-':
case '_': case '_':
var i = Clicks.zoomLevels.indexOf(this.zoomLevel_); this.activePlayer_.zoomOut();
this.zoomLevel_ = Clicks.zoomLevels[i - 1] || this.zoomLevel_;
this.resizePlayer_(this.activePlayer_);
break; break;
case '+': case '+':
case '=': case '=':
var i = Clicks.zoomLevels.indexOf(this.zoomLevel_); this.activePlayer_.zoomIn();
this.zoomLevel_ = Clicks.zoomLevels[i + 1] || this.zoomLevel_;
this.resizePlayer_(this.activePlayer_);
break; break;
} }
this.fireConfigChange(); this.fireConfigChange();
@@ -819,12 +780,13 @@ Clicks.prototype.exitFullScreen_ = function() {
var ClicksVideo = function(youTubeAPIKey, id, playerNode, onReady) { var ClicksVideo = function(youTubeAPIKey, id, container, onReady) {
this.youTubeAPIKey_ = youTubeAPIKey; this.youTubeAPIKey_ = youTubeAPIKey;
this.id = id; this.id = id;
this.playerNode = playerNode; this.container_ = container;
this.onReady_ = onReady; this.onReady_ = onReady;
this.loading_ = true; this.loading_ = true;
this.zoomLevel_ = 1.0;
this.fetchVideoInfo_(id, this.onMetadataResponse_.bind(this)); this.fetchVideoInfo_(id, this.onMetadataResponse_.bind(this));
@@ -836,6 +798,65 @@ var ClicksVideo = function(youTubeAPIKey, id, playerNode, onReady) {
}; };
ClicksVideo.prototype.zoomLevels_ = function() {
// TODO: make this dynamic and refuse to zoom beyond 1:1
return [
1.0,
1.5,
2.0,
2.5,
3.0,
];
};
ClicksVideo.prototype.getZoomLevel = function() {
return this.zoomLevel_;
};
ClicksVideo.prototype.zoom = function(zoomLevel) {
// TODO: sotp overzoom
this.zoomLevel_ = zoomLevel;
this.resize();
};
ClicksVideo.prototype.zoomOut = function() {
var zoomLevels = this.zoomLevels_();
var i = zoomLevels.indexOf(this.zoomLevel_);
this.zoom(zoomLevels[i - 1] || this.zoomLevel_);
};
ClicksVideo.prototype.zoomIn = function() {
var zoomLevels = this.zoomLevels_();
var i = zoomLevels.indexOf(this.zoomLevel_);
this.zoom(zoomLevels[i + 1] || this.zoomLevel_);
};
ClicksVideo.prototype.unhide = function() {
this.playerContainer_.className =
'clicks-player-container clicks-player-container-active';
};
ClicksVideo.prototype.resize = function() {
var zoom = Math.min(
this.container_.clientWidth / this.videoRes[0],
this.container_.clientHeight / this.videoRes[1]);
zoom = Math.min(zoom * this.zoomLevel_, 1.0);
this.playerScale_.style.transform = [
'scale(' + zoom + ',' + zoom + ')',
].join(' ');
this.playerScale_.style.width = this.videoRes[0];
this.playerScale_.style.height = this.videoRes[1];
this.playerCrop_.style.width = Math.ceil(this.videoRes[0] * zoom);
this.playerCrop_.style.height = Math.ceil(this.videoRes[1] * zoom);
};
ClicksVideo.prototype.onMetadataResponse_ = function(response) { ClicksVideo.prototype.onMetadataResponse_ = function(response) {
this.metadata = this.parseVideoDescription_(response); this.metadata = this.parseVideoDescription_(response);
this.checkComplete_(); this.checkComplete_();
@@ -860,8 +881,17 @@ ClicksVideo.prototype.onPlayerStateChange_ = function(e) {
ClicksVideo.prototype.onAPIReady_ = function() { ClicksVideo.prototype.onAPIReady_ = function() {
this.playerContainer_ = Clicks.createElementAndAppend(
'clicks-player-container', this.container_);
this.playerCrop_ = Clicks.createElementAndAppend(
'clicks-player-crop', this.playerContainer_);
this.playerScale_ = Clicks.createElementAndAppend(
'clicks-player-scale', this.playerCrop_);
this.playerOverlay_ = Clicks.createElementAndAppend(
'clicks-player-overlay', this.playerScale_);
var tempNode = document.createElement('div'); var tempNode = document.createElement('div');
this.playerNode.appendChild(tempNode); this.playerScale_.appendChild(tempNode);
this.player = new YT.Player(tempNode, { this.player = new YT.Player(tempNode, {
height: '1080', height: '1080',
width: '1920', width: '1920',