|
|
@ -1,3 +1,163 @@ |
|
|
|
class Slide { |
|
|
|
constructor(slide, idx) { |
|
|
|
this.isInit = false |
|
|
|
this.el = slide |
|
|
|
this.idx = idx |
|
|
|
this.duration = slide.dataset.duration |
|
|
|
const video = slide.querySelector('.video') |
|
|
|
if (video) { |
|
|
|
this.video = load_urls(video.dataset) |
|
|
|
this.videoVolume = video.dataset.volume ? parseFloat(video.dataset.volume) : 1 |
|
|
|
this.videoContainer = video |
|
|
|
if (this.video.length > 1) { |
|
|
|
this.zooms = this.video.map(url => url.split('/').pop().split('#')[0].split(',').map(a => Math.round(a))) |
|
|
|
} |
|
|
|
} |
|
|
|
const audio = slide.querySelector('.audio') |
|
|
|
if (audio) { |
|
|
|
this.audio = audio.dataset.url // audio does not need to be an array
|
|
|
|
this.audioVolume = audio.dataset.volume ? parseFloat(audio.dataset.volume) : 1 |
|
|
|
this.audioContainer = audio |
|
|
|
this.audioContinue = !!audio.dataset.continue |
|
|
|
} |
|
|
|
this.initEmbeds() |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
initEmbeds() { |
|
|
|
if (this.video) { |
|
|
|
const videoEmbed = this.videoEmbed = new PandoraEmbed({ |
|
|
|
id: 'slide-' + this.idx, |
|
|
|
url: this.video[0], |
|
|
|
container: this.videoContainer |
|
|
|
}) |
|
|
|
|
|
|
|
videoEmbed.on('init', (data) => { |
|
|
|
this.isVideoInit = true |
|
|
|
}) |
|
|
|
|
|
|
|
videoEmbed.on('playing', (positionData) => { |
|
|
|
if (!this.videoStart) { |
|
|
|
this.videoStart = positionData.position |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
if (this.audio) { |
|
|
|
const audioEmbed = this.audioEmbed = new PandoraEmbed({ |
|
|
|
id: 'audio-' + this.idx, |
|
|
|
url: this.audio, |
|
|
|
container: this.audioContainer |
|
|
|
}) |
|
|
|
|
|
|
|
audioEmbed.on('init', (data) => { |
|
|
|
this.isAudioInit = true |
|
|
|
}) |
|
|
|
|
|
|
|
audioEmbed.on('playing', (positionData) => { |
|
|
|
if (!this.audioStart) { |
|
|
|
this.audioStart = positionData.position |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
sendToBack() { |
|
|
|
this.el.style.zIndex = 0 |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
bringToFront() { |
|
|
|
this.el.style.zIndex = 10 |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
start() { |
|
|
|
if (this.zooms) { |
|
|
|
this.startZoom() |
|
|
|
} else if (this.video && this.video.length) { |
|
|
|
this.startVideo() |
|
|
|
} |
|
|
|
if (this.audioContainer) { // if there is an audio container, we always stop current audio
|
|
|
|
reset_active_audio() |
|
|
|
} |
|
|
|
if (this.audio) { |
|
|
|
this.startAudio() |
|
|
|
} |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
stop() { |
|
|
|
if (this.zooms) { |
|
|
|
this.resetZoom() |
|
|
|
} else if (this.video && this.video.length) { |
|
|
|
this.resetVideo() |
|
|
|
} |
|
|
|
if (this.audio && !this.audioContinue) { |
|
|
|
this.resetAudio() |
|
|
|
} |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
startZoom() { |
|
|
|
for (var i=1; i<this.zooms.length; i++) { |
|
|
|
this.zoomTimeouts = []; |
|
|
|
((j) => { |
|
|
|
this.zoomTimeouts.push(setTimeout(() => { |
|
|
|
this.videoEmbed.postMessage('options', { |
|
|
|
'area': this.zooms[j] |
|
|
|
}) |
|
|
|
}, Math.round(1000 * (this.duration / this.zooms.length) * j))) |
|
|
|
})(i); |
|
|
|
} |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
startVideo() { |
|
|
|
this.videoEmbed.postMessage('options', { |
|
|
|
'paused': false, |
|
|
|
'volume': this.videoVolume |
|
|
|
}) |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
startAudio() { |
|
|
|
this.audioEmbed.postMessage('options', { |
|
|
|
'paused': false, |
|
|
|
'volume': this.audioVolume |
|
|
|
}) |
|
|
|
activeAudio = this |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
resetZoom() { |
|
|
|
this.zoomTimeouts.forEach(timeout => clearTimeout(timeout)) |
|
|
|
this.videoEmbed.postMessage('options', { |
|
|
|
'area': this.zooms[0] |
|
|
|
}) |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
resetVideo() { |
|
|
|
this.videoEmbed.postMessage('options', { |
|
|
|
'paused': true, |
|
|
|
'position': this.start || 0 |
|
|
|
}) |
|
|
|
return this |
|
|
|
} |
|
|
|
|
|
|
|
resetAudio() { |
|
|
|
this.audioEmbed.postMessage('options', { |
|
|
|
'paused': true, |
|
|
|
'position': 0 //FIXME: figure correct audio reset
|
|
|
|
}) |
|
|
|
activeAudio = null; |
|
|
|
return this |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var slides = [], |
|
|
|
slideData = [], |
|
|
|
current = 0, |
|
|
@ -8,33 +168,25 @@ var slides = [], |
|
|
|
init() |
|
|
|
|
|
|
|
function init() { |
|
|
|
document.querySelectorAll('.slide').forEach(function(slide) { |
|
|
|
slides.push(slide) |
|
|
|
var data = slideData[slides.length - 1] = load_slide(slide); |
|
|
|
data.idx = slides.length - 1; |
|
|
|
if (data.video && data.video.length) { |
|
|
|
data.embed = init_embed(data) |
|
|
|
} |
|
|
|
if (data.audio) { |
|
|
|
data.audioEmbed = init_audio_embed(data) |
|
|
|
} |
|
|
|
document.querySelectorAll('.slide').forEach(function(slide, idx) { |
|
|
|
slides.push(new Slide(slide, idx)) |
|
|
|
}) |
|
|
|
go(0) |
|
|
|
} |
|
|
|
|
|
|
|
function go(idx) { |
|
|
|
var old = current |
|
|
|
slides[current].style.zIndex = 0 |
|
|
|
slides[idx].style.zIndex = 10 |
|
|
|
slides[current].sendToBack() |
|
|
|
slides[idx].bringToFront() |
|
|
|
current = idx |
|
|
|
if (timeout) { |
|
|
|
clearTimeout(timeout) |
|
|
|
timeout = null |
|
|
|
} |
|
|
|
timeout = setTimeout(next, Math.round(slides[current].dataset.duration) * 1000) |
|
|
|
timeout = setTimeout(next, Math.round(slides[current].duration) * 1000) |
|
|
|
|
|
|
|
stop(old) |
|
|
|
start(current) |
|
|
|
slides[old].stop() |
|
|
|
slides[current].start() |
|
|
|
} |
|
|
|
|
|
|
|
function next() { |
|
|
@ -51,34 +203,6 @@ function previous() { |
|
|
|
go(idx) |
|
|
|
} |
|
|
|
|
|
|
|
function start(idx) { |
|
|
|
var data = slideData[idx] |
|
|
|
console.log('start', current, data) |
|
|
|
if (data.zooms) { |
|
|
|
start_zoom(data) |
|
|
|
} else if (data.video && data.video.length) { |
|
|
|
start_video(data) |
|
|
|
} |
|
|
|
if (data.audioContainer) { // if there is an audio container, we always stop current audio
|
|
|
|
reset_active_audio(); |
|
|
|
} |
|
|
|
if (data.audio) { |
|
|
|
start_audio(data) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function stop(idx) { |
|
|
|
var data = slideData[idx] |
|
|
|
console.log(current, data) |
|
|
|
if (data.zooms) { |
|
|
|
reset_zoom(data) |
|
|
|
} else if (data.video && data.video.length) { |
|
|
|
reset_video(data) |
|
|
|
} |
|
|
|
if (data.audio && !data.audioContinue) { |
|
|
|
reset_audio(data) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function load_urls(dataset) { |
|
|
|
var urls = [], idx = 0 |
|
|
@ -89,56 +213,6 @@ function load_urls(dataset) { |
|
|
|
return urls |
|
|
|
} |
|
|
|
|
|
|
|
function load_slide(slide) { |
|
|
|
var data = {} |
|
|
|
data.duration = slide.dataset.duration |
|
|
|
var video = slide.querySelector('.video') |
|
|
|
if (video) { |
|
|
|
data.video = load_urls(video.dataset) |
|
|
|
data.videoVolume = video.dataset.volume ? parseFloat(video.dataset.volume) : 1 |
|
|
|
data.container = video |
|
|
|
|
|
|
|
// assumes documents if length > 1
|
|
|
|
if (data.video.length > 1) { |
|
|
|
data.zooms = data.video.map(url => url.split('/').pop().split('#')[0].split(',').map(a => Math.round(a))) |
|
|
|
} |
|
|
|
} |
|
|
|
var audio = slide.querySelector('.audio') |
|
|
|
if (audio) { |
|
|
|
data.audio = audio.dataset.url // audio does not need to be an array
|
|
|
|
data.audioVolume = audio.dataset.volume ? parseFloat(audio.dataset.volume) : 1 |
|
|
|
data.audioContainer = audio |
|
|
|
console.log('continue', audio.dataset.continue) |
|
|
|
data.audioContinue = !!audio.dataset.continue |
|
|
|
} |
|
|
|
return data |
|
|
|
} |
|
|
|
|
|
|
|
function init_embed(data) { |
|
|
|
var embed = window.currentEmbed = new PandoraEmbed({ |
|
|
|
id: 'slide-' + data.idx, |
|
|
|
url: data.video[0], |
|
|
|
container: data.container |
|
|
|
}); |
|
|
|
embed.on('init', function(data) { |
|
|
|
|
|
|
|
}); |
|
|
|
embed.on('playing', function(positionData) { |
|
|
|
if (!slideData[data.idx].start) { |
|
|
|
slideData[data.idx].start = positionData.position; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
return embed; |
|
|
|
} |
|
|
|
|
|
|
|
function init_audio_embed(data) { |
|
|
|
return new PandoraEmbed({ |
|
|
|
id: 'slide-audio-' + data.idx, |
|
|
|
url: data.audio, |
|
|
|
container: data.audioContainer |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
window.addEventListener('blur', function(){ |
|
|
|
setTimeout(function(){ |
|
|
@ -150,62 +224,9 @@ window.addEventListener('blur', function(){ |
|
|
|
}, false); |
|
|
|
|
|
|
|
|
|
|
|
function reset_zoom(data) { |
|
|
|
data.zoomTimeouts.forEach(timeout => clearTimeout(timeout)) |
|
|
|
data.embed.postMessage('options', { |
|
|
|
'area': data.zooms[0] |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
function start_zoom(data) { |
|
|
|
// console.log('start zoon', Math.round(1000 * data.duration / 2))
|
|
|
|
|
|
|
|
for (var i=1; i<data.zooms.length; i++) { |
|
|
|
data.zoomTimeouts = []; |
|
|
|
(function(j) { |
|
|
|
data.zoomTimeouts.push(setTimeout(function() { |
|
|
|
data.embed.postMessage('options', { |
|
|
|
'area': data.zooms[j] |
|
|
|
}) |
|
|
|
}, Math.round(1000 * (data.duration / data.zooms.length) * j))) |
|
|
|
})(i) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function start_video(data) { |
|
|
|
data.embed.postMessage('options', { |
|
|
|
'paused': false, |
|
|
|
'volume': data.videoVolume |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
function start_audio(data) { |
|
|
|
data.audioEmbed.postMessage('options', { |
|
|
|
'paused': false, |
|
|
|
'volume': data.audioVolume |
|
|
|
}) |
|
|
|
activeAudio = data |
|
|
|
} |
|
|
|
|
|
|
|
function reset_video(data) { |
|
|
|
data.embed.postMessage('options', { |
|
|
|
'paused': true, |
|
|
|
'position': data.start || 0 |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
function reset_audio(data) { |
|
|
|
data.audioEmbed.postMessage('options', { |
|
|
|
'paused': true, |
|
|
|
'position': 0 //FIXME: figure correct audio reset
|
|
|
|
}) |
|
|
|
activeAudio = null; |
|
|
|
} |
|
|
|
|
|
|
|
function reset_active_audio() { |
|
|
|
if (activeAudio) { |
|
|
|
reset_audio(activeAudio) |
|
|
|
activeAudio.resetAudio() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|