Campomigliaio collegato (strada, circolino, ponte), il Poggio verso la Fortezza; Ringraziamenti coi ritratti e il carosello
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
+52
-2
@@ -106,11 +106,61 @@ function openCredits() {
|
||||
$('credits-list').replaceChildren(...shuffledCredits(story.credits ?? []).flatMap(({ role, names }) => {
|
||||
const dt = document.createElement('dt'), dd = document.createElement('dd');
|
||||
dt.textContent = role;
|
||||
dd.replaceChildren(...names.map(n => Object.assign(document.createElement('span'), { textContent: n })));
|
||||
dd.replaceChildren(...names.map(n => {
|
||||
if (typeof n === 'string') return Object.assign(document.createElement('span'), { textContent: n });
|
||||
// Chi ha il ritratto: il nome è un pulsante che lo mostra.
|
||||
const b = Object.assign(document.createElement('button'), { type: 'button', className: 'credit-face', textContent: n.name });
|
||||
b.addEventListener('click', () => showFace(n));
|
||||
return b;
|
||||
}));
|
||||
return [dt, dd];
|
||||
}));
|
||||
fillReel();
|
||||
$('credits').hidden = false;
|
||||
rollCredits();
|
||||
}
|
||||
// Sotto i nomi, un carosello che scorre da solo: gli sfondi del paese e i ritratti, due giri uguali in fila per non
|
||||
// vedere mai la cucitura.
|
||||
function fillReel() {
|
||||
const track = $('credits-reel').querySelector('.track');
|
||||
if (track.children.length) return;
|
||||
const pictures = [...new Set(Object.values(story.scenes).map(s => s.background).filter(Boolean))];
|
||||
const faces = (story.credits ?? []).flatMap(c => c.names).filter(n => n.face).map(n => n.face);
|
||||
// I ritratti sparsi fra gli sfondi, uno ogni quattro.
|
||||
const all = pictures.flatMap((p, i) => i % 4 === 3 && faces.length ? [p, faces[(i >> 2) % faces.length]] : [p]);
|
||||
for (const src of [...all, ...all]) {
|
||||
const img = Object.assign(document.createElement('img'), { src, alt: '', loading: 'lazy', decoding: 'async' });
|
||||
if (src.includes('/credits/')) img.className = 'face';
|
||||
track.append(img);
|
||||
}
|
||||
}
|
||||
// I nomi salgono piano da soli; si fermano se ci si passa sopra o si tocca, e ricominciano dall'alto in fondo.
|
||||
let rolling = 0, rollWait = 0;
|
||||
$('credits-list').addEventListener('pointerdown', () => { rollWait = 4000; });
|
||||
$('credits-list').addEventListener('wheel', () => { rollWait = 4000; }, { passive: true });
|
||||
function rollCredits() {
|
||||
const list = $('credits-list');
|
||||
list.scrollTop = 0;
|
||||
cancelAnimationFrame(rolling);
|
||||
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
let last = performance.now(), pos = 0;
|
||||
rollWait = 1500;
|
||||
const step = now => {
|
||||
if ($('credits').hidden) return;
|
||||
const dt = now - last; last = now;
|
||||
if (list.matches(':hover') || !$('face').hidden || (rollWait -= dt) > 0) pos = list.scrollTop;
|
||||
else if (list.scrollTop + list.clientHeight >= list.scrollHeight - 1) { rollWait = 2500; list.scrollTop = pos = 0; }
|
||||
else list.scrollTop = pos += dt * 0.025;
|
||||
rolling = requestAnimationFrame(step);
|
||||
};
|
||||
rolling = requestAnimationFrame(step);
|
||||
}
|
||||
function showFace({ name, face }) {
|
||||
$('face').querySelector('img').src = face;
|
||||
$('face').querySelector('figcaption').textContent = name;
|
||||
$('face').hidden = false;
|
||||
}
|
||||
$('face').addEventListener('click', () => { $('face').hidden = true; });
|
||||
for (const b of document.querySelectorAll('.open-credits')) b.addEventListener('click', openCredits);
|
||||
$('close-credits').addEventListener('click', () => { $('credits').hidden = true; });
|
||||
|
||||
@@ -414,7 +464,7 @@ window.addEventListener('keydown', e => {
|
||||
return;
|
||||
}
|
||||
if (debugKey(e)) return;
|
||||
if (!$('credits').hidden) { if (e.key === 'Escape') $('credits').hidden = true; return; }
|
||||
if (!$('credits').hidden) { if (e.key === 'Escape') { if (!$('face').hidden) $('face').hidden = true; else $('credits').hidden = true; } return; }
|
||||
if (!$('pause').hidden) { if (e.key === 'Escape') closePause(); return; }
|
||||
if (!$('map').hidden) { if (e.key === 'Escape' || e.key === 'p' || e.key === 'P') $('map').hidden = true; return; }
|
||||
if ((e.key === 'p' || e.key === 'P') && running) { openMap(); return; }
|
||||
|
||||
Reference in New Issue
Block a user