User:Monster Domosed/common.js: Difference between revisionsGive feedback
No edit summary |
No edit summary |
||
| Line 43: | Line 43: | ||
var cur = startFrame, | var cur = startFrame, | ||
is2D = false, | is2D = false, | ||
dragOK = true; | dragOK = true, | ||
ready = false; // true once the strip image has loaded | |||
/* ============================================================ | /* ============================================================ | ||
3D SPRITE STRIP | 3D SPRITE STRIP | ||
============================================================ */ | ============================================================ */ | ||
var img | var img = makeImg(imageUrl, '', 'rm-strip'); | ||
// Set explicit display dimensions | |||
// width = single frame width × number of frames | |||
// height = frame height | |||
img.style.height = fh + 'px'; | img.style.height = fh + 'px'; | ||
img.style.width = (fw * count) + 'px'; | img.style.width = (fw * count) + 'px'; | ||
img.addEventListener('load', function () { | img.addEventListener('load', function () { | ||
ready = true; | |||
if (load) load.style.display = 'none'; | if (load) load.style.display = 'none'; | ||
show(startFrame); | show(startFrame); | ||
| Line 64: | Line 68: | ||
el.insertBefore(img, el.firstChild); | el.insertBefore(img, el.firstChild); | ||
// Handle cached images | |||
if (img.complete && img.naturalWidth > 0) { | if (img.complete && img.naturalWidth > 0) { | ||
ready = true; | |||
if (load) load.style.display = 'none'; | if (load) load.style.display = 'none'; | ||
show(startFrame); | |||
} | } | ||
| Line 91: | Line 98: | ||
toggleBtn.title = 'Switch to 2D'; | toggleBtn.title = 'Switch to 2D'; | ||
if (icon2dUrl) { | if (icon2dUrl) { | ||
iconImg2d = makeImg(icon2dUrl, '2D', 'rm-mode-icon rm-icon-2d'); | iconImg2d = makeImg(icon2dUrl, '2D', 'rm-mode-icon rm-icon-2d'); | ||
| Line 97: | Line 103: | ||
if (icon3dUrl) { | if (icon3dUrl) { | ||
iconImg3d = makeImg(icon3dUrl, '3D', 'rm-mode-icon rm-icon-3d'); | iconImg3d = makeImg(icon3dUrl, '3D', 'rm-mode-icon rm-icon-3d'); | ||
iconImg3d.style.display = 'none'; | iconImg3d.style.display = 'none'; | ||
} | } | ||
if (iconImg2d) toggleBtn.appendChild(iconImg2d); | if (iconImg2d) toggleBtn.appendChild(iconImg2d); | ||
if (iconImg3d) toggleBtn.appendChild(iconImg3d); | if (iconImg3d) toggleBtn.appendChild(iconImg3d); | ||
if (!icon2dUrl && !icon3dUrl) { | if (!icon2dUrl && !icon3dUrl) { | ||
toggleBtn.textContent = '2D'; | toggleBtn.textContent = '2D'; | ||
| Line 128: | Line 131: | ||
function show(idx) { | function show(idx) { | ||
cur = ((idx % count) + count) % count; | cur = ((idx % count) + count) % count; | ||
img.style.left = -(cur | // Move the strip so that frame `cur` is visible in the viewport | ||
var offset = cur * fw; | |||
img.style.left = '-' + offset + 'px'; | |||
img.style.top = '0px'; | |||
} | |||
function nudge(d) { | |||
if (!is2D && ready) { | |||
show(cur + d); | |||
hideHint(); | |||
} | |||
} | |||
function reset() { show(startFrame); } | |||
function hideHint() { | |||
if (hint) hint.classList.add('rm-hidden'); | |||
} | } | ||
/* ============================================================ | /* ============================================================ | ||
| Line 150: | Line 166: | ||
} | } | ||
if (iconImg2d && iconImg3d) { | if (iconImg2d && iconImg3d) { | ||
iconImg2d.style.display = is2D ? 'none' : ''; | iconImg2d.style.display = is2D ? 'none' : ''; | ||
iconImg3d.style.display = is2D ? '' : 'none'; | iconImg3d.style.display = is2D ? '' : 'none'; | ||
} | } | ||
if (toggleBtn) { | if (toggleBtn) { | ||
toggleBtn.title = is2D ? 'Switch to 3D' : 'Switch to 2D'; | toggleBtn.title = is2D ? 'Switch to 3D' : 'Switch to 2D'; | ||
if (!icon2dUrl && !icon3dUrl) { | if (!icon2dUrl && !icon3dUrl) { | ||
toggleBtn.textContent = is2D ? '3D' : '2D'; | toggleBtn.textContent = is2D ? '3D' : '2D'; | ||
| Line 177: | Line 187: | ||
/* ============================================================ | /* ============================================================ | ||
DRAG (mouse + touch) | DRAG (mouse + touch) | ||
One frame per `sensitivity` pixels of movement. | |||
Clamped to ±1 frame per event to prevent skipping. | |||
============================================================ */ | ============================================================ */ | ||
function startDrag(x0) { | function startDrag(x0) { | ||
if (!dragOK) return; | if (!dragOK || !ready) return; | ||
var acc = 0; | var acc = 0; | ||
hideHint(); | hideHint(); | ||
function move(cx) { | function move(cx) { | ||
var dx = cx - x0; | |||
x0 = cx; | x0 = cx; | ||
acc += dx; | |||
// Convert accumulated pixels to frame steps | |||
while (acc >= sensitivity) { | |||
acc -= sensitivity; | |||
show(cur + 1); | |||
} | |||
while (acc <= -sensitivity) { | |||
acc += sensitivity; | |||
show(cur - 1); | |||
} | |||
} | } | ||
| Line 222: | Line 243: | ||
}, { passive: false }); | }, { passive: false }); | ||
/* ---- wheel ---- */ | /* ---- wheel: always ±1 frame per tick ---- */ | ||
el.addEventListener('wheel', function (e) { | el.addEventListener('wheel', function (e) { | ||
if (!dragOK) return; | if (!dragOK || !ready) return; | ||
var d = e.deltaY > 0 ? 1 : e.deltaY < 0 ? -1 : 0; | var d = e.deltaY > 0 ? 1 : e.deltaY < 0 ? -1 : 0; | ||
if (d) { nudge(d); e.preventDefault(); } | if (d) { nudge(d); e.preventDefault(); } | ||
| Line 232: | Line 253: | ||
el.setAttribute('tabindex', '0'); | el.setAttribute('tabindex', '0'); | ||
el.addEventListener('keydown', function (e) { | el.addEventListener('keydown', function (e) { | ||
if (is2D) return; | if (is2D || !ready) return; | ||
if (e.key === 'ArrowLeft') { nudge(-1); e.preventDefault(); } | if (e.key === 'ArrowLeft') { nudge(-1); e.preventDefault(); } | ||
if (e.key === 'ArrowRight') { nudge( 1); e.preventDefault(); } | if (e.key === 'ArrowRight') { nudge( 1); e.preventDefault(); } | ||