Implements a Slide class #6
|
@ -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 = [],
|
var slides = [],
|
||||||
slideData = [],
|
slideData = [],
|
||||||
current = 0,
|
current = 0,
|
||||||
|
@ -8,33 +168,25 @@ var slides = [],
|
||||||
init()
|
init()
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
document.querySelectorAll('.slide').forEach(function(slide) {
|
document.querySelectorAll('.slide').forEach(function(slide, idx) {
|
||||||
slides.push(slide)
|
slides.push(new Slide(slide, idx))
|
||||||
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)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
go(0)
|
go(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
function go(idx) {
|
function go(idx) {
|
||||||
var old = current
|
var old = current
|
||||||
slides[current].style.zIndex = 0
|
slides[current].sendToBack()
|
||||||
slides[idx].style.zIndex = 10
|
slides[idx].bringToFront()
|
||||||
current = idx
|
current = idx
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
clearTimeout(timeout)
|
clearTimeout(timeout)
|
||||||
timeout = null
|
timeout = null
|
||||||
}
|
}
|
||||||
timeout = setTimeout(next, Math.round(slides[current].dataset.duration) * 1000)
|
timeout = setTimeout(next, Math.round(slides[current].duration) * 1000)
|
||||||
|
|
||||||
stop(old)
|
slides[old].stop()
|
||||||
start(current)
|
slides[current].start()
|
||||||
}
|
}
|
||||||
|
|
||||||
function next() {
|
function next() {
|
||||||
|
@ -51,34 +203,6 @@ function previous() {
|
||||||
go(idx)
|
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) {
|
function load_urls(dataset) {
|
||||||
var urls = [], idx = 0
|
var urls = [], idx = 0
|
||||||
|
@ -89,56 +213,6 @@ function load_urls(dataset) {
|
||||||
return urls
|
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(){
|
window.addEventListener('blur', function(){
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
|
@ -150,62 +224,9 @@ window.addEventListener('blur', function(){
|
||||||
}, false);
|
}, 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() {
|
function reset_active_audio() {
|
||||||
if (activeAudio) {
|
if (activeAudio) {
|
||||||
reset_audio(activeAudio)
|
activeAudio.resetAudio()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user