diff --git a/script.js b/script.js index 07b1358..e1f8adc 100644 --- a/script.js +++ b/script.js @@ -399,8 +399,8 @@ const indexedDBStorage = { const request = index.getAll(); request.onsuccess = () => { const images = request.result || []; - // 按时间戳排序 - images.sort((a, b) => a.timestamp - b.timestamp); + // 按时间戳倒序排序(最新的在前) + images.sort((a, b) => b.timestamp - a.timestamp); resolve(images.map(img => ({ id: img.imageId, url: img.url @@ -797,7 +797,7 @@ const uiController = { `; - gallery.appendChild(imageDiv); + gallery.insertBefore(imageDiv, gallery.firstChild); // 添加事件监听器 const viewLargeBtn = imageDiv.querySelector('.view-large-btn'); @@ -805,6 +805,9 @@ const uiController = { const copyBtn = imageDiv.querySelector('.copy-url-btn'); const removeBtn = imageDiv.querySelector('.remove-btn'); + // 添加移动端触摸交互 + this.addMobileTouchInteraction(imageDiv); + if (viewLargeBtn) { viewLargeBtn.addEventListener('click', (e) => { e.stopPropagation(); @@ -833,8 +836,8 @@ const uiController = { }); } - // 添加到内存中的图像记录 - generatedImages.push({ id: imageId, url: imageUrl }); + // 添加到内存中的图像记录(插入到最前面) + generatedImages.unshift({ id: imageId, url: imageUrl }); // 显示"全部下载"按钮 this.updateDownloadAllButtonVisibility(); @@ -868,7 +871,7 @@ const uiController = { `; - gallery.appendChild(placeholderDiv); + gallery.insertBefore(placeholderDiv, gallery.firstChild); return placeholderDiv; }, @@ -911,6 +914,9 @@ const uiController = { const copyBtn = placeholder.querySelector('.copy-url-btn'); const removeBtn = placeholder.querySelector('.remove-btn'); + // 添加移动端触摸交互 + this.addMobileTouchInteraction(placeholder); + if (viewLargeBtn) { viewLargeBtn.addEventListener('click', (e) => { e.stopPropagation(); @@ -939,8 +945,8 @@ const uiController = { }); } - // 添加到内存中的图像记录 - generatedImages.push({ id: imageId, url: imageUrl }); + // 添加到内存中的图像记录(插入到最前面) + generatedImages.unshift({ id: imageId, url: imageUrl }); // 显示"全部下载"按钮 this.updateDownloadAllButtonVisibility(); @@ -1255,6 +1261,61 @@ const uiController = { this.updateNavigationButtons(); }, + // 添加移动端触摸交互 + addMobileTouchInteraction: function(imageElement) { + if (!imageElement) return; + + let touchTimeout = null; + let isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0; + + if (!isTouchDevice) return; // 非触摸设备不需要添加此交互 + + // 添加触摸开始事件 + const touchStartHandler = (e) => { + // 清除之前的超时 + if (touchTimeout) { + clearTimeout(touchTimeout); + } + + // 添加touched类 + imageElement.classList.add('touched'); + + // 设置超时,3秒后自动移除touched类 + touchTimeout = setTimeout(() => { + imageElement.classList.remove('touched'); + }, 3000); + }; + + // 添加点击外部移除touched类的逻辑 + const documentClickHandler = (e) => { + if (!imageElement.contains(e.target)) { + imageElement.classList.remove('touched'); + if (touchTimeout) { + clearTimeout(touchTimeout); + } + } + }; + + // 绑定事件 + imageElement.addEventListener('touchstart', touchStartHandler, { passive: true }); + imageElement.addEventListener('click', touchStartHandler); // 也支持点击 + + // 存储清理函数,以便后续清理 + imageElement._cleanupMobileTouch = () => { + imageElement.removeEventListener('touchstart', touchStartHandler); + imageElement.removeEventListener('click', touchStartHandler); + document.removeEventListener('click', documentClickHandler); + if (touchTimeout) { + clearTimeout(touchTimeout); + } + }; + + // 添加到全局点击监听器(延迟添加避免立即触发) + setTimeout(() => { + document.addEventListener('click', documentClickHandler); + }, 100); + }, + // 显示图像预览 displayImagePreview: function(imageData) { const preview = document.getElementById('imagePreview'); @@ -1405,7 +1466,7 @@ const uiController = { `; - gallery.appendChild(imageDiv); + gallery.appendChild(imageDiv); // 由于数据库查询已经是倒序,这里用appendChild保持顺序 // 添加事件监听器 const viewLargeBtn = imageDiv.querySelector('.view-large-btn'); @@ -1413,6 +1474,9 @@ const uiController = { const copyBtn = imageDiv.querySelector('.copy-url-btn'); const removeBtn = imageDiv.querySelector('.remove-btn'); + // 添加移动端触摸交互 + this.addMobileTouchInteraction(imageDiv); + if (viewLargeBtn) { viewLargeBtn.addEventListener('click', (e) => { e.stopPropagation(); @@ -1457,6 +1521,10 @@ const uiController = { imageElements.forEach(element => { const removeBtn = element.querySelector('.remove-btn'); if (removeBtn && removeBtn.dataset.imageId == imageId) { + // 清理移动端触摸事件监听器 + if (element._cleanupMobileTouch) { + element._cleanupMobileTouch(); + } element.remove(); } }); diff --git a/styles.css b/styles.css index f0e852a..7e5b044 100644 --- a/styles.css +++ b/styles.css @@ -239,6 +239,57 @@ body { opacity: 1; } +/* 移动端触摸设备优化 */ +@media (hover: none) and (pointer: coarse) { + /* 在触摸设备上,overlay始终可见但透明度较低 */ + .image-overlay { + opacity: 0.3; + background: rgba(0, 0, 0, 0.5); + } + + /* 点击时显示完整overlay */ + .image-item:active .image-overlay, + .image-item.touched .image-overlay { + opacity: 1; + background: rgba(0, 0, 0, 0.8); + } + + /* 为触摸设备添加点击提示 */ + .image-item::after { + content: "轻触显示操作"; + position: absolute; + bottom: 8px; + left: 50%; + transform: translateX(-50%); + background: rgba(0, 0, 0, 0.7); + color: white; + padding: 4px 8px; + border-radius: 12px; + font-size: 12px; + opacity: 0.6; + pointer-events: none; + z-index: 1; + } + + .image-item.touched::after { + opacity: 0; + } +} + +/* 在小屏幕设备上也应用类似效果 */ +@media (max-width: 768px) { + .image-overlay { + opacity: 0.4; + background: rgba(0, 0, 0, 0.6); + } + + .image-item:active .image-overlay, + .image-item.touched .image-overlay { + opacity: 1; + background: rgba(0, 0, 0, 0.8); + } +} + /* 状态指示器 */ .status-indicator { display: inline-block; @@ -554,6 +605,40 @@ body { .btn-grid-row .btn { flex: 1; min-width: 0; + min-height: 36px; + font-size: 14px; +} + +/* 移动端按钮优化 */ +@media (max-width: 768px) { + .btn-grid { + gap: 8px; + } + + .btn-grid-row { + gap: 8px; + } + + .btn-grid-row .btn { + min-height: 44px; /* 增加触摸目标大小 */ + font-size: 16px; + padding: 8px; + } +} + +/* 触摸设备专用样式 */ +@media (hover: none) and (pointer: coarse) { + .btn-grid-row .btn { + min-height: 48px; /* 更大的触摸目标 */ + font-size: 18px; + padding: 10px; + transition: all 0.2s ease; + } + + .btn-grid-row .btn:active { + transform: scale(0.95); + opacity: 0.8; + } } /* 错误状态 */