html player
This commit is contained in:
parent
3edc89d305
commit
1a9f9ecbc1
3 changed files with 368 additions and 0 deletions
BIN
player/html/Menlo-Regular.ttf
Normal file
BIN
player/html/Menlo-Regular.ttf
Normal file
Binary file not shown.
1
player/html/ass.global.min.js
vendored
Normal file
1
player/html/ass.global.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
367
player/html/index.html
Normal file
367
player/html/index.html
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>30 Box Grid</title>
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Menlo';
|
||||
src: url('Menlo-Regular.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
font-family: Menlo, sans-serif;
|
||||
}
|
||||
|
||||
/* Full page container */
|
||||
.page {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
background: rgba(0,0,0, 0.5);
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* Grid container */
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 70px);
|
||||
grid-template-rows: repeat(3, 70px);
|
||||
gap: 12px;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
/* Individual boxes */
|
||||
.box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #ffff;
|
||||
background: rgba(0,0,0, 0.6);
|
||||
border: 2px solid #333;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
transition: background 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.box:hover {
|
||||
background: #e0e0e0;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Title display */
|
||||
.title {
|
||||
min-height: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #ffff;
|
||||
}
|
||||
body {
|
||||
background: black;
|
||||
}
|
||||
video {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
#stage {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
video.next {
|
||||
display: none;
|
||||
}
|
||||
#subtitles {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Menlo';
|
||||
src: url('Menlo-Regular.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
<script src="ass.global.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
|
||||
const sub_handlers = {};
|
||||
var playlist = [
|
||||
"/01_Life/front.mp4",
|
||||
"/02_Seeing/front.mp4",
|
||||
"/03_Capacity/front.mp4",
|
||||
"/04_Landscape/front.mp4",
|
||||
"/05_Relations/front.mp4",
|
||||
"/06_Will/front.mp4",
|
||||
"/07_Self/front.mp4",
|
||||
"/08_Field/front.mp4",
|
||||
"/09_Theatre/front.mp4",
|
||||
"/10_Substance/front.mp4",
|
||||
"/11_Science/front.mp4",
|
||||
"/12_Energy/front.mp4",
|
||||
"/13_Geopolitics/front.mp4",
|
||||
"/14__Chance/front.mp4",
|
||||
"/15_Morality/front.mp4",
|
||||
"/16_Evolution/front.mp4",
|
||||
"/17_Computing/front.mp4",
|
||||
"/18_Semi-Conductors/front.mp4",
|
||||
"/19_Love/front.mp4",
|
||||
"/20_Reversibility/front.mp4",
|
||||
"/21_Weakness/front.mp4",
|
||||
"/22_Elections/front.mp4",
|
||||
"/23_People/front.mp4",
|
||||
"/24_Corporation/front.mp4",
|
||||
"/25_Instruments/front.mp4",
|
||||
"/26_Practice/front.mp4",
|
||||
"/27_Weaponry/front.mp4",
|
||||
"/28_Art/front.mp4",
|
||||
"/29_Help/front.mp4",
|
||||
"/30_Self-help/front.mp4",
|
||||
]
|
||||
//var prefix = '../render/'
|
||||
var prefix = 'https://power.0x2620.org/static/render/'
|
||||
var current = 0, name
|
||||
var currentVideo, nextVideo;
|
||||
function ended(event) {
|
||||
const next = nextVideo;
|
||||
currentVideo.classList.add('next')
|
||||
sub_handlers[currentVideo.id]?.destroy()
|
||||
nextVideo.classList.remove('next')
|
||||
console.log("play next", nextVideo)
|
||||
nextVideo.play()
|
||||
sub_handlers[nextVideo.id]?.show()
|
||||
current +=1
|
||||
if (current >= playlist.length) {
|
||||
current = 0
|
||||
}
|
||||
currentVideo.src = prefix + name + playlist[current]
|
||||
nextVideo = currentVideo
|
||||
currentVideo = next
|
||||
sub_handlers[nextVideo.id]?.destroy()
|
||||
fetch(nextVideo.src.replace(/.mp4/, '.ass')).then(async (res) => {
|
||||
const content = await res.text()
|
||||
const ass = new ASS(content, nextVideo, {
|
||||
container: subtitles,
|
||||
});
|
||||
sub_handlers[nextVideo.id] = ass
|
||||
})
|
||||
}
|
||||
|
||||
const titles = [
|
||||
"Life",
|
||||
"Seeing",
|
||||
"Capacity",
|
||||
"Landscape",
|
||||
"Relations",
|
||||
"Will",
|
||||
"Self",
|
||||
"Field",
|
||||
"Theatre",
|
||||
"Substance",
|
||||
"Science",
|
||||
"Energy",
|
||||
"Geopolitics",
|
||||
"Chance",
|
||||
"Morality",
|
||||
"Evolution",
|
||||
"Computing",
|
||||
"Semi-Conductors",
|
||||
"Love",
|
||||
"Reversibility",
|
||||
"Weakness",
|
||||
"Elections",
|
||||
"People",
|
||||
"Corporation",
|
||||
"Instruments",
|
||||
"Practice",
|
||||
"Weaponry",
|
||||
"Art",
|
||||
"Help",
|
||||
"Self-help",
|
||||
];
|
||||
|
||||
|
||||
function render() {
|
||||
name = document.location.hash.slice(1)
|
||||
const parts = name.split('/')
|
||||
if (parts.length == 2) {
|
||||
name = parts[0]
|
||||
current = parseInt(parts[1]) - 1
|
||||
}
|
||||
var body = document.querySelector('body')
|
||||
body.innerHTML = ``
|
||||
var stage = document.createElement("div")
|
||||
stage.id = "stage"
|
||||
body.appendChild(stage)
|
||||
|
||||
var overlay = document.createElement("div")
|
||||
overlay.id = "overlay"
|
||||
body.appendChild(overlay)
|
||||
overlay.innerHTML = `
|
||||
<div class="page">
|
||||
<div class="grid" id="grid"></div>
|
||||
<div class="title" id="title"></div>
|
||||
</div>
|
||||
`
|
||||
const grid = overlay.querySelector("#grid");
|
||||
const titleEl = overlay.querySelector("#title");
|
||||
for (let i = 1; i <= 30; i++) {
|
||||
const box = document.createElement("div");
|
||||
box.className = "box";
|
||||
box.textContent = i;
|
||||
|
||||
box.addEventListener("mouseenter", () => {
|
||||
titleEl.textContent = titles[i - 1];
|
||||
});
|
||||
|
||||
box.addEventListener("mouseleave", () => {
|
||||
titleEl.textContent = "";
|
||||
});
|
||||
box.addEventListener("click", () => {
|
||||
console.log("clicked", box.textContent)
|
||||
document.querySelector(".page").style.display = ""
|
||||
current = parseInt(box.textContent) - 1
|
||||
nextVideo.src = prefix + name + playlist[current]
|
||||
fetch(nextVideo.src.replace(/.mp4/, '.ass')).then(async (res) => {
|
||||
const content = await res.text()
|
||||
const ass = new ASS(content, nextVideo, {
|
||||
container: subtitles,
|
||||
});
|
||||
sub_handlers[nextVideo.id] = ass
|
||||
ended()
|
||||
})
|
||||
});
|
||||
|
||||
grid.appendChild(box);
|
||||
}
|
||||
|
||||
var subtitles = document.createElement("div")
|
||||
subtitles.id = "subtitles"
|
||||
stage.appendChild(subtitles)
|
||||
|
||||
var video1 = document.createElement("video")
|
||||
video1.src = prefix + name + playlist[current]
|
||||
video1.id = 'v1'
|
||||
video1.controls = false
|
||||
video1.preload = "auto"
|
||||
video1.addEventListener('ended', ended)
|
||||
stage.appendChild(video1)
|
||||
currentVideo = video1
|
||||
|
||||
current +=1
|
||||
var video2 = document.createElement("video")
|
||||
video2.src = prefix + name + playlist[current]
|
||||
video1.id = 'v2'
|
||||
video2.classList.add("next")
|
||||
video2.controls = false
|
||||
video2.preload = "auto"
|
||||
video2.addEventListener('ended', ended)
|
||||
stage.appendChild(video2)
|
||||
nextVideo = video2
|
||||
|
||||
var audio2 = document.createElement("audio")
|
||||
audio2.src = prefix + 'forest-5.1.mp4'
|
||||
audio2.controls = false
|
||||
audio2.volume = 1
|
||||
audio2.loop = true
|
||||
audio2.autoplay = true
|
||||
audio2.classList.add("forest")
|
||||
body.appendChild(audio2)
|
||||
|
||||
var audio3 = document.createElement("audio")
|
||||
audio3.src = prefix + 'music-5.1.mp4'
|
||||
audio3.controls = false
|
||||
audio3.volume = 1
|
||||
audio3.loop = true
|
||||
audio3.autoplay = true
|
||||
audio3.currentTime = Math.random() * 60
|
||||
audio3.classList.add("music")
|
||||
body.appendChild(audio3)
|
||||
|
||||
document.querySelectorAll('video,audio').forEach(media => {
|
||||
media.addEventListener('play', sync)
|
||||
media.addEventListener('pause', sync)
|
||||
media.addEventListener('click', () => {
|
||||
document.querySelector(".page").style.display = "flex"
|
||||
})
|
||||
})
|
||||
fetch(video1.src.replace(/.mp4/, '.ass')).then(async (res) => {
|
||||
const content = await res.text()
|
||||
const ass = new ASS(content, video1, {
|
||||
container: subtitles,
|
||||
});
|
||||
sub_handlers[video1.id] = ass
|
||||
sub_handlers[video1.id].show()
|
||||
})
|
||||
video1.play()
|
||||
fetch(video2.src.replace(/.mp4/, '.ass')).then(async (res) => {
|
||||
const content = await res.text()
|
||||
const ass = new ASS(content, video2, {
|
||||
container: subtitles,
|
||||
});
|
||||
sub_handlers[video2.id] = ass
|
||||
})
|
||||
}
|
||||
function sync(event) {
|
||||
var src = event.target
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
return
|
||||
document.querySelectorAll('video,audio').forEach(media => {
|
||||
if (media.classList.contains('next')) {
|
||||
return
|
||||
}
|
||||
if (media != src) {
|
||||
if (!src.paused) {
|
||||
console.log("play", media.id)
|
||||
media.play()
|
||||
} else {
|
||||
console.log("pause", media.id, src.paused)
|
||||
media.pause()
|
||||
}
|
||||
media.paused = src.paused
|
||||
if (media.classList.contains('music') || media.classList.contains('forest')) {
|
||||
//
|
||||
} else {
|
||||
//media.currentTime = src.currentTime
|
||||
console.log(media.currentTime, src.currentTime)
|
||||
}
|
||||
console.log(media, media.paused, src.paused)
|
||||
}
|
||||
})
|
||||
}
|
||||
window.addEventListener("hashchange", event=>{
|
||||
render()
|
||||
})
|
||||
|
||||
if (!document.location.hash.slice(1).length) {
|
||||
document.location.hash = '#0'
|
||||
}
|
||||
render()
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue