User:Monster Domosed/common.js: Difference between revisionsGive feedback
Undo Tag: Undo |
No edit summary |
||
| Line 2: | Line 2: | ||
* Rotatable Model Viewer — with 2D / 3D toggle | * Rotatable Model Viewer — with 2D / 3D toggle | ||
* All <img> elements created in JS to bypass MediaWiki sanitizer. | * All <img> elements created in JS to bypass MediaWiki sanitizer. | ||
* | |||
* The rotatable sprite is always rendered at 1:1 (square) aspect, | |||
* using min(width, height) as the side length, centred in the viewport. | |||
*/ | */ | ||
(function () { | (function () { | ||
| Line 30: | Line 33: | ||
startFrame = +el.dataset.startFrame || 0, | startFrame = +el.dataset.startFrame || 0, | ||
sensitivity = +el.dataset.sensitivity || 5; | sensitivity = +el.dataset.sensitivity || 5; | ||
/* ---- 1:1 square size & centering offsets ---- */ | |||
var sq = Math.min(fw, fh), | |||
offsetX = (fw - sq) / 2, | |||
offsetY = (fh - sq) / 2; | |||
var hint = el.querySelector('.rotatable-model-hint'), | var hint = el.querySelector('.rotatable-model-hint'), | ||
| Line 44: | Line 52: | ||
is2D = false, | is2D = false, | ||
dragOK = true, | dragOK = true, | ||
ready = false; | ready = false; | ||
/* ============================================================ | /* ============================================================ | ||
3D SPRITE STRIP | 3D SPRITE STRIP — displayed at sq × sq per frame | ||
============================================================ */ | ============================================================ */ | ||
var img = makeImg(imageUrl, '', 'rm-strip'); | var img = makeImg(imageUrl, '', 'rm-strip'); | ||
img.style.height = sq + 'px'; | |||
img.style.width = (sq * count) + 'px'; | |||
img.style.height = | |||
img.style.width = ( | |||
img.addEventListener('load', function () { | img.addEventListener('load', function () { | ||
| Line 68: | Line 73: | ||
el.insertBefore(img, el.firstChild); | el.insertBefore(img, el.firstChild); | ||
if (img.complete && img.naturalWidth > 0) { | if (img.complete && img.naturalWidth > 0) { | ||
ready = true; | ready = true; | ||
| Line 76: | Line 80: | ||
/* ============================================================ | /* ============================================================ | ||
2D STATIC IMAGE | 2D STATIC IMAGE — also shown at sq × sq, centred | ||
============================================================ */ | ============================================================ */ | ||
var staticImg = null; | var staticImg = null; | ||
if (image2dUrl) { | if (image2dUrl) { | ||
staticImg = makeImg(image2dUrl, '', 'rm-static'); | staticImg = makeImg(image2dUrl, '', 'rm-static'); | ||
staticImg.style.width = sq + 'px'; | |||
staticImg.style.height = sq + 'px'; | |||
staticImg.style.objectFit = 'contain'; | |||
staticImg.style.left = offsetX + 'px'; | |||
staticImg.style.top = offsetY + 'px'; | |||
el.insertBefore(staticImg, el.firstChild); | el.insertBefore(staticImg, el.firstChild); | ||
} | } | ||
| Line 127: | Line 136: | ||
/* ============================================================ | /* ============================================================ | ||
FRAME DISPLAY | FRAME DISPLAY — each frame is sq wide, centred in viewport | ||
============================================================ */ | ============================================================ */ | ||
function show(idx) { | function show(idx) { | ||
cur = ((idx % count) + count) % count; | cur = ((idx % count) + count) % count; | ||
img.style.left = (offsetX - cur * sq) + 'px'; | |||
img.style.top = offsetY + 'px'; | |||
img.style.left = | |||
img.style.top = ' | |||
} | } | ||
| Line 187: | Line 194: | ||
/* ============================================================ | /* ============================================================ | ||
DRAG (mouse + touch) | DRAG (mouse + touch) | ||
============================================================ */ | ============================================================ */ | ||
function startDrag(x0) { | function startDrag(x0) { | ||
| Line 200: | Line 205: | ||
acc += dx; | acc += dx; | ||
while (acc >= sensitivity) { | while (acc >= sensitivity) { | ||
acc -= sensitivity; | acc -= sensitivity; | ||
| Line 243: | Line 247: | ||
}, { passive: false }); | }, { passive: false }); | ||
el.addEventListener('wheel', function (e) { | el.addEventListener('wheel', function (e) { | ||
if (!dragOK || !ready) return; | if (!dragOK || !ready) return; | ||
| Line 250: | Line 253: | ||
}, { passive: false }); | }, { passive: false }); | ||
el.setAttribute('tabindex', '0'); | el.setAttribute('tabindex', '0'); | ||
el.addEventListener('keydown', function (e) { | el.addEventListener('keydown', function (e) { | ||
| Line 259: | Line 261: | ||
}); | }); | ||
if (wrap) { | if (wrap) { | ||
var bL = wrap.querySelector('.rm-btn-left'), | var bL = wrap.querySelector('.rm-btn-left'), | ||
| Line 269: | Line 270: | ||
} | } | ||
show(startFrame); | show(startFrame); | ||
} | } | ||
function initAll(root) { | function initAll(root) { | ||
var els = (root || document).querySelectorAll('.rotatable-model'); | var els = (root || document).querySelectorAll('.rotatable-model'); | ||