Просмотр исходного кода

Scale full image to viewport, scroll to it, expand on double-click, drag to pan

k4be 4 дней назад
Родитель
Сommit
5b0b59f431
2 измененных файлов с 119 добавлено и 1 удалено
  1. 105 1
      image.js
  2. 14 0
      style.css

+ 105 - 1
image.js

@@ -40,10 +40,12 @@ function setLinks(e) {
 		$('#imagelink').removeAttr('href');
 	}
     var image = $("#image");
+    image.removeClass('expanded');
     image.css('opacity', '0.2');
     image.attr('src', imageUrlPrefix + dirname + '/' + filename);
-    image.on('load', function() {
+    image.off('load').on('load', function() {
 	image.css('opacity', '1');
+	scrollToImage();
     });
     if (doPush)
 	window.history.pushState(currId, '', makeImageUrl(dirname, filename));
@@ -121,9 +123,111 @@ $(document).keydown(function(e) {
 	}
 });
 
+function initImageInteraction() {
+	var img = document.getElementById('image');
+	var imagelink = document.getElementById('imagelink');
+	var isDragging = false;
+	var hasDragged = false;
+	var startX, startY, scrollLeft, scrollTop;
+	var clickCount = 0;
+	var clickTimer = null;
+	var suppressNextClick = false;
+
+	/* intercept clicks in capture phase to distinguish single vs double click */
+	imagelink.addEventListener('click', function(e) {
+		e.stopPropagation();
+		e.preventDefault();
+
+		if (suppressNextClick) {
+			suppressNextClick = false;
+			return;
+		}
+
+		clickCount++;
+		clearTimeout(clickTimer);
+
+		if (clickCount >= 2) {
+			clickCount = 0;
+			img.classList.toggle('expanded');
+			if (!img.classList.contains('expanded')) {
+				img.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'nearest'});
+			}
+		} else {
+			clickTimer = setTimeout(function() {
+				clickCount = 0;
+				if (!img.classList.contains('expanded')) {
+					nextImage();
+				}
+			}, 250);
+		}
+	}, true);
+
+	img.addEventListener('mousedown', function(e) {
+		if (!img.classList.contains('expanded') || e.button !== 0) return;
+		isDragging = true;
+		hasDragged = false;
+		startX = e.clientX;
+		startY = e.clientY;
+		scrollLeft = window.scrollX;
+		scrollTop = window.scrollY;
+		img.classList.add('dragging');
+		e.preventDefault();
+	});
+
+	document.addEventListener('mousemove', function(e) {
+		if (!isDragging) return;
+		var dx = e.clientX - startX;
+		var dy = e.clientY - startY;
+		if (Math.abs(dx) > 3 || Math.abs(dy) > 3) hasDragged = true;
+		window.scrollTo(scrollLeft - dx, scrollTop - dy);
+	});
+
+	document.addEventListener('mouseup', function() {
+		if (!isDragging) return;
+		isDragging = false;
+		img.classList.remove('dragging');
+		if (hasDragged) suppressNextClick = true;
+	});
+
+	img.addEventListener('touchstart', function(e) {
+		if (!img.classList.contains('expanded') || e.touches.length !== 1) return;
+		isDragging = true;
+		hasDragged = false;
+		startX = e.touches[0].clientX;
+		startY = e.touches[0].clientY;
+		scrollLeft = window.scrollX;
+		scrollTop = window.scrollY;
+	}, {passive: true});
+
+	img.addEventListener('touchmove', function(e) {
+		if (!isDragging || e.touches.length !== 1) return;
+		var dx = e.touches[0].clientX - startX;
+		var dy = e.touches[0].clientY - startY;
+		if (Math.abs(dx) > 3 || Math.abs(dy) > 3) hasDragged = true;
+		window.scrollTo(scrollLeft - dx, scrollTop - dy);
+		e.preventDefault();
+	}, {passive: false});
+
+	img.addEventListener('touchend', function() {
+		isDragging = false;
+	});
+}
+
+function scrollToImage() {
+	var img = document.getElementById('image');
+	img.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'nearest'});
+}
+
 $(document).ready(function() {
 	getImgList();
 	$('body').on('swipeleft', nextImage);
 	$('body').on('swiperight', prevImage);
+	initImageInteraction();
+	var img = document.getElementById('image');
+	if (img.complete) {
+		scrollToImage();
+	} else {
+		img.addEventListener('load', scrollToImage, {once: true});
+	}
 });
 

+ 14 - 0
style.css

@@ -15,6 +15,20 @@ img:hover {
 
 img.pelny {
 	border-color: red;
+	max-width: 95vw;
+	max-height: 85vh;
+	cursor: zoom-in;
+	scroll-margin: 12px;
+}
+
+img.pelny.expanded {
+	max-width: none;
+	max-height: none;
+	cursor: grab;
+}
+
+img.pelny.expanded.dragging {
+	cursor: grabbing;
 }
 
 #poprz,#nast,.k4,.gora {