Files
presentation-html/assets/app.js
T

64 lines
4.3 KiB
JavaScript

(() => {
const {createTimeline, stagger} = anime;
const reduced = matchMedia('(prefers-reduced-motion: reduce)');
const printMode = location.search.includes('print-pdf');
const seen = new Set(), timelines = new Map(); let motion = !reduced.matches;
const motionButton = document.querySelector('#motion');
// Explicit paused instances: Reveal owns slide navigation; one clock owns motion.
// Targets are dedicated motion wrappers, not positioned/rotated diagram parts.
document.querySelectorAll('.slides>section').forEach(slide=>{
const targets=[...slide.querySelectorAll('[data-motion]')];
if(!targets.length)return;
const tl=createTimeline({autoplay:false,defaults:{duration:300,ease:'outCubic'}});
if(slide.id==='sequence') {
['observe','interpret','act'].forEach((label,i)=>{
tl.label(label,i*180).add(targets[i],{opacity:[0,1],translateY:[12,0]},label);
});
} else tl.add(targets,{opacity:[0,1],translateY:[12,0],delay:stagger(70),duration:400},0);
tl.seek(tl.duration);tl.pause();timelines.set(slide,tl);
});
const allowed=()=>motion&&!reduced.matches&&!printMode&&!Reveal.isOverview();
function settle() {
timelines.forEach(tl=>{tl.pause();tl.seek(tl.duration);});
}
function replay() {
settle();const tl=timelines.get(Reveal.getCurrentSlide());
if(!tl||!allowed())return false;
tl.seek(0);tl.play();return true;
}
function seek(timeMs) {
if(!Number.isFinite(timeMs))throw new TypeError('seek requires finite milliseconds');
const tl=timelines.get(Reveal.getCurrentSlide());
if(!tl)return false;
tl.pause();tl.seek(allowed()?Math.max(0,Math.min(timeMs,tl.duration)):tl.duration);
return true;
}
function run() {
settle();const slide=Reveal.getCurrentSlide();
if(!slide||seen.has(slide.id)||!allowed())return;
seen.add(slide.id);replay();
}
function motionLabel(){motionButton.textContent=motion&&!reduced.matches?'Motion on':'Motion off';motionButton.setAttribute('aria-pressed',String(motion&&!reduced.matches));}
motionButton.onclick=()=>{motion=!motion;settle();motionLabel();};
reduced.addEventListener('change',()=>{if(reduced.matches)settle();motionLabel();});motionLabel();
addEventListener('beforeprint',settle);
const fs=document.querySelector('#fullscreen');
async function fullscreen(){try{if(document.fullscreenElement)await document.exitFullscreen();else await document.documentElement.requestFullscreen();}catch{fs.textContent='Fullscreen unavailable';}}
fs.onclick=fullscreen;
document.addEventListener('fullscreenchange',()=>{fs.textContent=document.fullscreenElement?'Exit fullscreen':'Enter fullscreen';fs.setAttribute('aria-pressed',String(!!document.fullscreenElement));});
document.addEventListener('keydown',e=>{if(e.key.toLowerCase()==='f'&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&!e.target.matches('input,textarea,[contenteditable]')){e.preventDefault();e.stopPropagation();fullscreen();}},true);
document.querySelectorAll('[data-node]').forEach(node=>{
function select(){const was=node.getAttribute('aria-pressed')==='true';document.querySelectorAll('[data-node]').forEach(n=>n.setAttribute('aria-pressed','false'));node.setAttribute('aria-pressed',String(!was));document.querySelector('#detail').textContent=was?'Select a source to reveal its role. Tab + Enter or Space also works.':node.dataset.detail;}
node.addEventListener('click',select);
node.addEventListener('keydown',e=>{if(e.key==='Enter'||e.key===' '){e.preventDefault();e.stopPropagation();select();}});
});
Reveal.initialize({width:1240,height:700,margin:.08,center:false,hash:true,transition:'none',backgroundTransition:'none',slideNumber:'c/t',view:'slide',keyboard:{70:null},autoAnimate:false}).then(()=>{
if(!location.hash){try{const i=Number(localStorage.getItem('presentation-html-demo-slide'));if(Number.isInteger(i)&&i>=0&&i<Reveal.getTotalSlides())Reveal.slide(i);}catch{}}
run(); window.deckReady=true;
});
Reveal.on('slidechanged',()=>{try{localStorage.setItem('presentation-html-demo-slide',String(Reveal.getIndices().h));}catch{}run();});
Reveal.on('overviewshown',settle);
document.addEventListener('visibilitychange',()=>{if(document.hidden)settle();});
window.presentationQA={settle,seek,replay,reduced:()=>reduced.matches,active:()=>[...timelines.values()].filter(tl=>!tl.paused&&!tl.completed).length};
})();