docs(slides): add slides v1
This commit is contained in:
69
docs/slides/script.js
Normal file
69
docs/slides/script.js
Normal file
@@ -0,0 +1,69 @@
|
||||
const slides = [...document.querySelectorAll('.slide')];
|
||||
const counter = document.getElementById('counter');
|
||||
const progressBar = document.getElementById('progressBar');
|
||||
const notesBox = document.getElementById('speakerNotes');
|
||||
let index = 0;
|
||||
|
||||
function fitDeck() {
|
||||
const vw = window.innerWidth;
|
||||
const vh = window.innerHeight;
|
||||
const root = document.documentElement;
|
||||
|
||||
// Mobile uses normal document flow, so text can shrink and content can scroll.
|
||||
if (vw <= 900) {
|
||||
const mobileScale = Math.max(0.64, Math.min(0.9, vw / 900));
|
||||
root.style.setProperty('--slide-scale', mobileScale.toFixed(3));
|
||||
root.style.removeProperty('--slide-w');
|
||||
root.style.removeProperty('--slide-h');
|
||||
return;
|
||||
}
|
||||
|
||||
// Desktop/tablet: keep a 16:9 slide and fill as much height as the viewport allows.
|
||||
const pad = Math.max(24, Math.min(72, Math.min(vw, vh) * 0.065));
|
||||
const availableW = vw - pad;
|
||||
const availableH = vh - pad;
|
||||
let slideW = Math.min(availableW, availableH * (16 / 9));
|
||||
let slideH = slideW * (9 / 16);
|
||||
|
||||
// If the width-bound calculation is too tall, bind by height instead.
|
||||
if (slideH > availableH) {
|
||||
slideH = availableH;
|
||||
slideW = slideH * (16 / 9);
|
||||
}
|
||||
|
||||
const scale = Math.max(0.78, Math.min(1.55, Math.min(slideW / 1200, slideH / 675)));
|
||||
root.style.setProperty('--slide-w', `${Math.floor(slideW)}px`);
|
||||
root.style.setProperty('--slide-h', `${Math.floor(slideH)}px`);
|
||||
root.style.setProperty('--slide-scale', scale.toFixed(3));
|
||||
}
|
||||
|
||||
function update() {
|
||||
slides.forEach((slide, i) => slide.classList.toggle('active', i === index));
|
||||
counter.textContent = `${index + 1} / ${slides.length}`;
|
||||
progressBar.style.width = `${((index + 1) / slides.length) * 100}%`;
|
||||
const note = slides[index].querySelector('.notes')?.textContent.trim() || '';
|
||||
notesBox.textContent = note;
|
||||
}
|
||||
|
||||
function go(delta) {
|
||||
index = Math.min(slides.length - 1, Math.max(0, index + delta));
|
||||
update();
|
||||
}
|
||||
|
||||
document.getElementById('prev').addEventListener('click', () => go(-1));
|
||||
document.getElementById('next').addEventListener('click', () => go(1));
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (['ArrowRight', 'PageUp'].includes(e.key)) go(-1);
|
||||
if (['ArrowLeft', 'PageDown', ' '].includes(e.key)) go(1);
|
||||
if (e.key.toLowerCase() === 'n') notesBox.classList.toggle('show');
|
||||
if (e.key.toLowerCase() === 'f') {
|
||||
if (!document.fullscreenElement) document.documentElement.requestFullscreen?.();
|
||||
else document.exitFullscreen?.();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', fitDeck);
|
||||
window.addEventListener('orientationchange', fitDeck);
|
||||
fitDeck();
|
||||
update();
|
||||
Reference in New Issue
Block a user