This commit is contained in:
2026-08-09 23:42:23 +02:00
parent 21da2edd79
commit bd2ccdf73e
46 changed files with 3540 additions and 788 deletions
+59
View File
@@ -0,0 +1,59 @@
// ── Pepsi gallery: shuffled on load, swipe cycles through on click ─
(function () {
const COUNT = 20;
const img = document.querySelector('.pepsi-placeholder img');
if (!img) return;
const box = img.parentElement;
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
const src = (n) => `Pepsi/Pepsi-${n}.jpg`;
// FisherYates shuffle of [1..COUNT]; clicks cycle through this order
const order = Array.from({ length: COUNT }, (_, i) => i + 1);
for (let i = order.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[order[i], order[j]] = [order[j], order[i]];
}
let pos = 0;
img.src = src(order[pos]);
const seen = (n) => { if (window.achv) window.achv.pepsi(n, COUNT); };
seen(order[pos]);
let busy = false;
box.addEventListener('click', () => {
if (busy) return;
if (window.achv) window.achv.mark('pepsi');
pos = (pos + 1) % order.length;
const next = order[pos];
if (reduceMotion.matches) {
img.src = src(next);
seen(next);
return;
}
busy = true;
const incoming = new Image();
incoming.src = src(next);
incoming.alt = img.alt;
incoming.draggable = false;
incoming.className = 'pepsi-incoming';
// Decode before animating so the swipe never reveals a half-loaded frame
incoming.decode().then(() => {
box.appendChild(incoming);
seen(next);
const opts = { duration: 300, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' };
img.animate(
[{ transform: 'translateX(0)' }, { transform: 'translateX(-100%)' }],
opts
);
incoming.animate(
[{ transform: 'translateX(100%)' }, { transform: 'translateX(0)' }],
opts
).finished.then(() => {
img.src = incoming.src; // already decoded, swaps instantly
incoming.remove();
busy = false;
});
}).catch(() => { busy = false; });
});
})();