2021-09-30 17:09:42 +00:00
|
|
|
var cache = cache || {}
|
|
|
|
var layer = 'descriptions'
|
|
|
|
var baseURL = 'https://pad.ma'
|
|
|
|
var imageResolution = 480
|
|
|
|
|
|
|
|
async function pandoraAPI(action, data) {
|
|
|
|
var url = baseURL + '/api/'
|
|
|
|
//var url = '/pandoraAPI/'
|
|
|
|
var key = JSON.stringify([action, data])
|
|
|
|
if (!cache[key]) {
|
|
|
|
var response = await fetch(url, {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {'Content-Type': 'application/json'},
|
|
|
|
body: JSON.stringify({
|
|
|
|
action: action,
|
|
|
|
data: data
|
|
|
|
})
|
|
|
|
})
|
|
|
|
cache[key] = await response.json()
|
|
|
|
}
|
|
|
|
return cache[key]
|
|
|
|
}
|
|
|
|
|
2021-10-10 15:46:19 +00:00
|
|
|
function updatePlayer(video, frame, currentTime, out, src) {
|
2021-09-30 17:09:42 +00:00
|
|
|
var rect = frame.getBoundingClientRect();
|
|
|
|
video.style.opacity = 0
|
|
|
|
video.style.top = (rect.top + window.scrollY) + 'px'
|
|
|
|
video.style.display = 'block';
|
2021-10-10 15:06:43 +00:00
|
|
|
if (src) {
|
|
|
|
video.src = src
|
|
|
|
}
|
2021-09-30 17:09:42 +00:00
|
|
|
//video.poster = frame.querySelector('img').src
|
2021-10-11 18:43:44 +00:00
|
|
|
var muted = video.muted
|
|
|
|
video.muted = true
|
2021-09-30 17:09:42 +00:00
|
|
|
video.currentTime = currentTime
|
2021-10-10 15:46:19 +00:00
|
|
|
video.dataset.in = currentTime
|
|
|
|
video.dataset.out = out
|
2021-10-11 09:28:51 +00:00
|
|
|
video._frame = frame
|
2021-10-11 18:43:44 +00:00
|
|
|
const show = event => {
|
|
|
|
video.style.opacity = 1
|
|
|
|
video.muted = muted
|
|
|
|
video.removeEventListener('seeked', show)
|
|
|
|
}
|
|
|
|
video.addEventListener('seeked', show)
|
2021-09-30 17:09:42 +00:00
|
|
|
video.play()
|
|
|
|
}
|
|
|
|
|
|
|
|
function isElementInViewport (el) {
|
|
|
|
var rect = el.getBoundingClientRect();
|
|
|
|
return (
|
|
|
|
rect.top >= 0 &&
|
|
|
|
rect.left >= 0 &&
|
|
|
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /* or $(window).height() */
|
|
|
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onVisibilityChange(el, callback) {
|
|
|
|
var old_visible;
|
|
|
|
return function () {
|
|
|
|
var visible = isElementInViewport(el);
|
|
|
|
if (visible != old_visible) {
|
|
|
|
old_visible = visible;
|
|
|
|
if (typeof callback == 'function') {
|
|
|
|
callback(visible);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 09:28:51 +00:00
|
|
|
function scrollTo(element) {
|
|
|
|
var delta = element.offsetTop - document.scrollingElement.scrollTop,
|
|
|
|
duration = 1000, t = 40, n = duration / t,
|
|
|
|
step = delta / n;
|
|
|
|
|
|
|
|
function scroll() {
|
|
|
|
if (document.scrollingElement.scrollTop + step > element.offsetTop) {
|
|
|
|
document.scrollingElement.scrollTop = element.offsetTop
|
|
|
|
n = 0
|
|
|
|
} else {
|
|
|
|
document.scrollingElement.scrollTop += step
|
|
|
|
}
|
|
|
|
n--
|
|
|
|
if (n) setTimeout(scroll, t)
|
|
|
|
}
|
|
|
|
scroll()
|
|
|
|
}
|
|
|
|
|
2021-10-10 15:46:19 +00:00
|
|
|
function timeupdate(event) {
|
|
|
|
if (event.target.dataset.out && event.target.dataset.in) {
|
|
|
|
var in_= parseFloat(event.target.dataset.in)
|
|
|
|
var out_= parseFloat(event.target.dataset.out)
|
|
|
|
if (event.target.currentTime >= out_) {
|
2021-10-11 09:28:51 +00:00
|
|
|
/*
|
|
|
|
var next
|
|
|
|
if (event.target._frame) {
|
|
|
|
next = event.target._frame.parentElement.nextSibling
|
|
|
|
if (next) {
|
|
|
|
next = next.querySelector('.frame')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (next) {
|
|
|
|
scrollTo(next)
|
|
|
|
} else {
|
|
|
|
event.target.pause()
|
|
|
|
}
|
|
|
|
*/
|
2021-10-10 15:46:19 +00:00
|
|
|
event.target.currentTime = in_
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 13:50:19 +00:00
|
|
|
function formatInfo(config, ascroll) {
|
|
|
|
var h1 = document.createElement('h1')
|
|
|
|
h1.innerHTML = config.title
|
|
|
|
ascroll.appendChild(h1)
|
|
|
|
var h2 = document.createElement('h2')
|
|
|
|
h2.innerHTML = config.byline
|
|
|
|
ascroll.appendChild(h2)
|
|
|
|
var div = document.createElement('div')
|
|
|
|
div.classList.add('intro')
|
|
|
|
div.innerHTML = config.body
|
|
|
|
ascroll.appendChild(div)
|
|
|
|
}
|
|
|
|
|
2021-10-11 18:43:44 +00:00
|
|
|
function showOverlay(event) {
|
|
|
|
document.querySelectorAll('#video-overlay').forEach(element => element.remove())
|
|
|
|
var video = event.target
|
|
|
|
var rect = video.getBoundingClientRect();
|
|
|
|
var overlay = document.createElement('div')
|
|
|
|
overlay.id = 'video-overlay'
|
|
|
|
overlay.style.top = video.style.top
|
|
|
|
overlay.style.width = rect.width + 'px'
|
|
|
|
overlay.style.height = (rect.height - 40) + 'px'
|
|
|
|
overlay.style.position = 'absolute'
|
|
|
|
overlay.style.display = 'flex'
|
|
|
|
overlay.style.alignItems = 'center'
|
|
|
|
overlay.style.justifyContent = 'center'
|
|
|
|
overlay.style.fontSize = '45px'
|
2021-10-11 18:52:29 +00:00
|
|
|
video.controls = true
|
2021-10-11 18:43:44 +00:00
|
|
|
|
|
|
|
if (video.muted) {
|
|
|
|
overlay.innerHTML = `🔇`
|
|
|
|
} else {
|
|
|
|
overlay.innerHTML = `🔊`
|
|
|
|
}
|
|
|
|
overlay.addEventListener('click', event=> {
|
|
|
|
video.muted = !video.muted
|
|
|
|
if (video.muted) {
|
|
|
|
overlay.innerHTML = `🔇`
|
|
|
|
} else {
|
|
|
|
overlay.innerHTML = `🔊`
|
|
|
|
}
|
|
|
|
})
|
2021-10-11 18:52:29 +00:00
|
|
|
var timeout = setTimeout(() => {
|
|
|
|
video.controls = false
|
2021-10-11 18:43:44 +00:00
|
|
|
overlay.remove()
|
2021-10-11 18:52:29 +00:00
|
|
|
}, 500)
|
|
|
|
overlay.addEventListener('mousemove', event=> {
|
|
|
|
clearTimeout(timeout)
|
|
|
|
timeout = setTimeout(() => {
|
|
|
|
video.controls = false
|
|
|
|
overlay.remove()
|
|
|
|
}, 500)
|
2021-10-11 18:43:44 +00:00
|
|
|
})
|
|
|
|
video.parentElement.appendChild(overlay)
|
2021-10-11 18:52:29 +00:00
|
|
|
|
2021-10-11 18:43:44 +00:00
|
|
|
}
|
|
|
|
|
2021-10-10 15:06:43 +00:00
|
|
|
function loadItem(config) {
|
2021-10-11 09:28:51 +00:00
|
|
|
pandoraAPI('get', {id: config.item, keys: [
|
|
|
|
'id', 'title', 'layers', 'hue', 'saturation', 'lightness'
|
|
|
|
]}).then(response => {
|
|
|
|
//var color = `hsl(${response.data.hue}, ${response.data.saturation * 100}%, ${response.data.lightness * 100}%)`
|
|
|
|
var color = `hsl(${response.data.hue}, 70%, 50%)`
|
|
|
|
//document.body.style.background = color
|
2021-10-10 15:06:43 +00:00
|
|
|
var ascroll = document.querySelector('#ascroll')
|
|
|
|
var loaded = false
|
2021-09-30 17:09:42 +00:00
|
|
|
|
2021-10-10 15:06:43 +00:00
|
|
|
var video = document.createElement('video')
|
|
|
|
video.classList.add('player')
|
|
|
|
video.muted = true
|
|
|
|
video.src = `${baseURL}/${config.item}/480p.webm`
|
2021-10-10 15:46:19 +00:00
|
|
|
video.addEventListener('timeupdate', timeupdate)
|
2021-10-11 18:43:44 +00:00
|
|
|
video.addEventListener('touchstart', showOverlay)
|
|
|
|
video.addEventListener('mouseover', showOverlay)
|
2021-10-10 15:06:43 +00:00
|
|
|
ascroll.appendChild(video)
|
2021-09-30 17:09:42 +00:00
|
|
|
|
2021-10-10 15:46:19 +00:00
|
|
|
var first
|
2021-10-11 13:50:19 +00:00
|
|
|
formatInfo(config, ascroll)
|
2021-09-30 17:09:42 +00:00
|
|
|
|
2021-10-10 15:06:43 +00:00
|
|
|
response.data.layers[layer].forEach(annotation => {
|
|
|
|
if (config.user && annotation.user != config.user) {
|
|
|
|
return
|
|
|
|
}
|
2021-10-10 15:46:19 +00:00
|
|
|
if (!first) {
|
|
|
|
first = annotation
|
|
|
|
}
|
2021-10-10 15:06:43 +00:00
|
|
|
var div = document.createElement('div')
|
|
|
|
div.classList.add('annotation')
|
|
|
|
div.innerHTML = `
|
|
|
|
<div class="frame"><img src="${baseURL}/${annotation.id.split('/')[0]}/${imageResolution}p${annotation.in}.jpg"></div>
|
|
|
|
<div class="text">${annotation.value}</div>
|
|
|
|
|
|
|
|
`
|
|
|
|
ascroll.appendChild(div)
|
|
|
|
var frame = div.querySelector('.frame')
|
|
|
|
document.addEventListener('scroll', onVisibilityChange(div.querySelector('.frame'), function(visible) {
|
|
|
|
if (loaded && visible)
|
2021-10-10 15:46:19 +00:00
|
|
|
updatePlayer(video, frame, annotation['in'], annotation['out'])
|
2021-10-10 15:06:43 +00:00
|
|
|
|
|
|
|
}))
|
|
|
|
})
|
|
|
|
loaded = true
|
|
|
|
let frame = ascroll.querySelector('.annotation .frame')
|
|
|
|
if (frame) {
|
2021-10-10 15:46:19 +00:00
|
|
|
updatePlayer(video, frame, first['in'], first['out'])
|
2021-10-10 15:06:43 +00:00
|
|
|
}
|
2021-09-30 17:09:42 +00:00
|
|
|
})
|
2021-10-10 15:06:43 +00:00
|
|
|
}
|
|
|
|
function loadEdit(config) {
|
|
|
|
pandoraAPI('getEdit', {id: config.edit, keys: []}).then(response => {
|
|
|
|
console.log(response)
|
|
|
|
var ascroll = document.querySelector('#ascroll')
|
|
|
|
var loaded = false
|
|
|
|
|
|
|
|
var video = document.createElement('video')
|
|
|
|
video.classList.add('player')
|
|
|
|
video.muted = true
|
2021-10-10 15:46:19 +00:00
|
|
|
video.addEventListener('timeupdate', timeupdate)
|
2021-10-10 15:06:43 +00:00
|
|
|
ascroll.appendChild(video)
|
|
|
|
|
|
|
|
var first
|
2021-10-11 13:50:19 +00:00
|
|
|
formatInfo(config, ascroll)
|
2021-10-10 15:06:43 +00:00
|
|
|
|
|
|
|
response.data.clips.forEach(clip => {
|
|
|
|
clip.layers[layer].forEach(annotation => {
|
|
|
|
if (config.user && annotation.user != config.user) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (!first) {
|
|
|
|
first = annotation
|
|
|
|
}
|
|
|
|
var div = document.createElement('div')
|
|
|
|
div.classList.add('annotation')
|
|
|
|
div.innerHTML = `
|
2021-10-10 15:25:17 +00:00
|
|
|
<div class="frame">
|
|
|
|
<figure>
|
|
|
|
<img src="${baseURL}/${annotation.id.split('/')[0]}/${imageResolution}p${annotation.in}.jpg">
|
|
|
|
<figcaption><a href="${baseURL}/${annotation.id}" target="_blank">${clip.title}</a></figcaption>
|
|
|
|
</figure>
|
|
|
|
|
|
|
|
</div>
|
2021-10-10 15:06:43 +00:00
|
|
|
<div class="text">${annotation.value}</div>
|
|
|
|
|
|
|
|
`
|
|
|
|
ascroll.appendChild(div)
|
|
|
|
var frame = div.querySelector('.frame')
|
|
|
|
document.addEventListener('scroll', onVisibilityChange(div.querySelector('.frame'), function(visible) {
|
|
|
|
var src = `${baseURL}/${annotation.id.split('/')[0]}/480p.webm`
|
|
|
|
if (loaded && visible)
|
2021-10-10 15:46:19 +00:00
|
|
|
updatePlayer(video, frame, annotation['in'], annotation['out'], src)
|
2021-10-10 15:06:43 +00:00
|
|
|
|
|
|
|
}))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
loaded = true
|
|
|
|
let frame = ascroll.querySelector('.annotation .frame')
|
|
|
|
if (frame) {
|
2021-10-10 15:25:17 +00:00
|
|
|
var src = `${baseURL}/${first.id.split('/')[0]}/480p.webm`
|
2021-10-10 15:46:19 +00:00
|
|
|
updatePlayer(video, frame, first['in'], first['out'], src)
|
2021-10-10 15:06:43 +00:00
|
|
|
}
|
2021-09-30 17:09:42 +00:00
|
|
|
})
|
2021-10-10 15:06:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (config.item) {
|
|
|
|
loadItem(config)
|
|
|
|
} else if (config.edit) {
|
|
|
|
loadEdit(config)
|
|
|
|
}
|