summaryrefslogtreecommitdiff
path: root/web/js/imageViewer.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/js/imageViewer.js')
-rw-r--r--web/js/imageViewer.js193
1 files changed, 0 insertions, 193 deletions
diff --git a/web/js/imageViewer.js b/web/js/imageViewer.js
deleted file mode 100644
index 09e1563..0000000
--- a/web/js/imageViewer.js
+++ /dev/null
@@ -1,193 +0,0 @@
-let els = () => ({});
-let isImageMode = () => false;
-let playNext = () => {};
-
-let zoomScale = 1;
-let panX = 0;
-let panY = 0;
-let isPanning = false;
-let panStart = { x: 0, y: 0 };
-let slideshowTimer = null;
-let slideshowPausedUntil = 0;
-let cropMode = false;
-let cropPositionX = 50;
-let cropPositionY = 50;
-const CROP_PRESETS = [
- { x: 50, y: 50, label: 'C' },
- { x: 50, y: 0, label: 'T' },
- { x: 50, y: 100, label: 'B' },
- { x: 0, y: 50, label: 'L' },
- { x: 100, y: 50, label: 'R' },
-];
-let cropPresetIndex = 0;
-
-export function initImageViewer(options = {}) {
- els = typeof options.els === 'function' ? options.els : els;
- isImageMode = typeof options.isImageMode === 'function' ? options.isImageMode : isImageMode;
- playNext = typeof options.playNext === 'function' ? options.playNext : playNext;
-
- const e = els();
- e.btnZoomIn?.addEventListener('click', () => { zoomIn(); pauseSlideshow(); });
- e.btnZoomOut?.addEventListener('click', () => { zoomOut(); pauseSlideshow(); });
- e.btnSlideshow?.addEventListener('click', toggleSlideshow);
-
- e.image?.addEventListener('mousedown', (ev) => {
- if (zoomScale > 1) {
- isPanning = true;
- panStart = { x: ev.clientX - panX, y: ev.clientY - panY };
- e.image.style.cursor = 'grabbing';
- ev.preventDefault();
- }
- });
- e.image?.addEventListener('wheel', (ev) => {
- ev.preventDefault();
- if (ev.deltaY < 0) zoomIn();
- else zoomOut();
- }, { passive: false });
- window.addEventListener('mousemove', (ev) => {
- if (!isPanning) return;
- panX = ev.clientX - panStart.x;
- panY = ev.clientY - panStart.y;
- applyImageTransform();
- });
- window.addEventListener('mouseup', () => {
- if (isPanning) {
- isPanning = false;
- const image = els().image;
- if (image) image.style.cursor = zoomScale > 1 ? 'grab' : 'zoom-in';
- }
- });
-}
-
-function setImageZoom(s) {
- zoomScale = Math.max(0.5, Math.min(s, 5));
- applyImageTransform();
-}
-
-function applyImageTransform() {
- const e = els();
- if (!e.image) return;
- e.image.style.transform = `translate(${panX}px, ${panY}px) scale(${zoomScale})`;
- e.image.style.cursor = zoomScale > 1 ? 'grab' : 'zoom-in';
-}
-
-export function resetImageZoom() {
- zoomScale = 1;
- panX = 0;
- panY = 0;
- applyImageTransform();
-}
-
-export function zoomIn() {
- setImageZoom(zoomScale * 1.25);
-}
-
-export function zoomOut() {
- setImageZoom(zoomScale / 1.25);
-}
-
-export function resetZoom() {
- resetImageZoom();
-}
-
-export function toggleSlideshow() {
- if (slideshowTimer) stopSlideshow();
- else startSlideshow();
-}
-
-export function isSlideshowActive() {
- return !!slideshowTimer;
-}
-
-function startSlideshow() {
- if (slideshowTimer) clearInterval(slideshowTimer);
- slideshowTimer = setInterval(() => {
- if (Date.now() < slideshowPausedUntil) return;
- if (!isImageMode()) { stopSlideshow(); return; }
- playNext();
- }, 5000);
- const btn = els().btnSlideshow;
- if (btn) btn.textContent = '⏸';
-}
-
-export function stopSlideshow() {
- clearInterval(slideshowTimer);
- slideshowTimer = null;
- const btn = els().btnSlideshow;
- if (btn) btn.textContent = '⏵';
-}
-
-export function pauseSlideshow() {
- slideshowPausedUntil = Date.now() + 10000;
-}
-
-export function toggleCrop() {
- const e = els();
- if (!e.player) return;
- if (!document.fullscreenElement) return;
- cropMode = !cropMode;
- e.player.classList.toggle('crop-mode', cropMode);
- if (!cropMode) {
- resetCropPosition();
- } else {
- applyCropPosition();
- }
-}
-
-function applyCropPosition() {
- const e = els();
- if (!e.player) return;
- e.player.style.setProperty('--crop-x', cropPositionX + '%');
- e.player.style.setProperty('--crop-y', cropPositionY + '%');
- updateCropIndicator();
-}
-
-function updateCropIndicator() {
- const e = els();
- if (!e.cropIndicator) return;
- if (!cropMode) {
- e.cropIndicator.classList.add('hidden');
- return;
- }
- const snap = 5;
- let label = '';
- if (Math.abs(cropPositionX - 50) <= snap && Math.abs(cropPositionY - 50) <= snap) label = 'C';
- else if (Math.abs(cropPositionX - 50) <= snap && cropPositionY <= snap) label = 'T';
- else if (Math.abs(cropPositionX - 50) <= snap && cropPositionY >= 95) label = 'B';
- else if (cropPositionX <= snap && Math.abs(cropPositionY - 50) <= snap) label = 'L';
- else if (cropPositionX >= 95 && Math.abs(cropPositionY - 50) <= snap) label = 'R';
- else label = Math.round(cropPositionX) + ',' + Math.round(cropPositionY);
- e.cropIndicator.textContent = label;
- e.cropIndicator.classList.remove('hidden');
-}
-
-export function resetCropPosition() {
- cropPositionX = 50;
- cropPositionY = 50;
- cropPresetIndex = 0;
- applyCropPosition();
-}
-
-export function clearCropMode() {
- cropMode = false;
- const e = els();
- e.player?.classList.remove('crop-mode');
- resetCropPosition();
-}
-
-export function shiftCropPosition(dx, dy) {
- if (!cropMode) return false;
- cropPositionX = Math.max(0, Math.min(100, cropPositionX + dx));
- cropPositionY = Math.max(0, Math.min(100, cropPositionY + dy));
- applyCropPosition();
- return true;
-}
-
-export function cycleCropPosition() {
- if (!cropMode) return;
- cropPresetIndex = (cropPresetIndex + 1) % CROP_PRESETS.length;
- const preset = CROP_PRESETS[cropPresetIndex];
- cropPositionX = preset.x;
- cropPositionY = preset.y;
- applyCropPosition();
-}