Make swipe animation interactive

This commit is contained in:
Kiyomichi Kosaka 2025-06-14 11:05:48 +02:00
parent 3757217c06
commit c4826a5306

View File

@ -869,27 +869,33 @@ function showEonstripDetails(index, startCobiets, opts) {
`;
}
function navigatePeriod(evt, direction) {
function getStep(mods) {
// base step = 1 megasequence
let step = 1;
if (evt.altKey && evt.shiftKey && evt.ctrlKey) {
if (mods.altKey && mods.shiftKey && mods.ctrlKey) {
// Epoch of Cosmos = 16⁵ MS
step = 16**5;
} else if (evt.altKey && evt.ctrlKey) {
step = 16 ** 5;
} else if (mods.altKey && mods.ctrlKey) {
// Celestial Era = 16⁴ MS
step = 16**4;
} else if (evt.altKey && evt.shiftKey) {
step = 16 ** 4;
} else if (mods.altKey && mods.shiftKey) {
// Universal Eon = 16³ MS
step = 16**3;
} else if (evt.altKey) {
step = 16 ** 3;
} else if (mods.altKey) {
// Galactic Year = 16² MS
step = 16**2;
} else if (evt.shiftKey) {
step = 16 ** 2;
} else if (mods.shiftKey) {
// Cosmocycle = 16¹ MS
step = 16**1;
step = 16 ** 1;
}
return step;
}
function navigatePeriod(evt, direction) {
const step = getStep(evt);
animateSwipe(direction, () => {
currentOffset += direction * step;
updateCalendar();
@ -1037,32 +1043,78 @@ document.getElementById('toggleExtended').addEventListener('click', () => {
// ── Swipe & Wheel Navigation ────────────────────────────────────────────────
let swipeStartX = null;
let swipeStartY = null;
let swipeMods = { altKey: false, shiftKey: false, ctrlKey: false };
let isSwiping = false;
let swipeGrid = null;
function swipeStart(e) {
const touch = e.touches ? e.touches[0] : e;
swipeStartX = touch.clientX;
swipeStartY = touch.clientY;
swipeMods = {
altKey: e.altKey || false,
shiftKey: e.shiftKey || false,
ctrlKey: e.ctrlKey || false
};
swipeGrid = document.getElementById('eonstripGrid');
if (swipeGrid) {
swipeGrid.style.transition = 'none';
}
isSwiping = true;
}
function swipeMove(e) {
if (!isSwiping || !swipeGrid) return;
const touch = e.touches ? e.touches[0] : e;
const dx = touch.clientX - swipeStartX;
const dy = touch.clientY - swipeStartY;
if (Math.abs(dx) > Math.abs(dy)) {
swipeGrid.style.transform = `translateX(${dx}px)`;
}
}
function swipeEnd(e) {
if (swipeStartX === null || swipeStartY === null) return;
if (!isSwiping || swipeStartX === null || swipeStartY === null) {
return;
}
const touch = e.changedTouches ? e.changedTouches[0] : e;
const dx = touch.clientX - swipeStartX;
const dy = touch.clientY - swipeStartY;
if (Math.abs(dx) > 40 && Math.abs(dx) > Math.abs(dy)) {
const direction = dx < 0 ? 1 : -1; // left → next, right → prev
navigatePeriod({
altKey: e.altKey || false,
shiftKey: e.shiftKey || false,
ctrlKey: e.ctrlKey || false
}, direction);
if (swipeGrid) {
const width = swipeGrid.clientWidth;
if (Math.abs(dx) > 40 && Math.abs(dx) > Math.abs(dy)) {
const direction = dx < 0 ? 1 : -1; // left → next
swipeGrid.style.transition = 'transform 0.2s ease';
swipeGrid.style.transform = `translateX(${dx < 0 ? -width : width}px)`;
swipeGrid.addEventListener('transitionend', function after() {
swipeGrid.removeEventListener('transitionend', after);
// prepare opposite side
swipeGrid.style.transition = 'none';
swipeGrid.style.transform = `translateX(${dx < 0 ? width : -width}px)`;
const step = getStep(swipeMods);
currentOffset += direction * step;
updateCalendar();
void swipeGrid.offsetWidth;
swipeGrid.style.transition = 'transform 0.3s ease';
swipeGrid.style.transform = 'translateX(0)';
});
} else {
swipeGrid.style.transition = 'transform 0.2s ease';
swipeGrid.style.transform = 'translateX(0)';
}
}
swipeStartX = swipeStartY = null;
isSwiping = false;
}
document.addEventListener('touchstart', swipeStart, {passive: true});
document.addEventListener('touchstart', swipeStart, { passive: true });
document.addEventListener('touchmove', swipeMove, { passive: true });
document.addEventListener('touchend', swipeEnd);
document.addEventListener('mousedown', swipeStart);
document.addEventListener('mousemove', swipeMove);
document.addEventListener('mouseup', swipeEnd);
function wheelNavigate(e) {