feat: Add zoom in/out controls for image preview

Features:
1. Zoom Controls
   - 🔍− button: zoom out (20% step)
   - 1:1 button: reset to 100%
   - 🔍+ button: zoom in (20% step)
   - Zoom level display: 100%, 120%, etc.

2. Zoom Range
   - Minimum: 20% (0.2x)
   - Maximum: 500% (5x)
   - Default: 100% (1x)

3. Auto-reset
   - Reset zoom to 100% when navigating photos
   - Reset when opening new image

4. Layout
   - Zoom buttons at top
   - Photo in scrollable container
   - Left/right arrows for navigation

Implementation:
- CSS transform: scale() for smooth zoom
- Remove max-width/max-height at high zoom
- Zoom level indicator updates dynamically

Files:
- src/page.html (zoomPhoto function, zoom UI)
This commit is contained in:
Warren
2026-05-17 05:37:49 +08:00
parent b5cf80e981
commit 09f0cb7ae9
2 changed files with 43 additions and 3 deletions

Binary file not shown.

View File

@@ -796,10 +796,22 @@ function showDetail(fuuid){
}else if(isDocPdf){
h+="<iframe sandbox='allow-same-origin' src='"+src+"' style='width:100%;height:400px;border:none;border-radius:8px;background:#fff'></iframe>";
}else{
h+="<div style='display:flex;flex-direction:column;align-items:center;width:100%'>";
h+="<div style='display:flex;gap:8px;margin-bottom:8px'>";
h+="<button onclick='zoomPhoto(-0.2)' style='background:#1e293b;border:1px solid #334155;color:#94a3b8;font-size:18px;padding:6px 12px;border-radius:6px;cursor:pointer'>🔍−</button>";
h+="<button onclick='zoomPhoto(0)' style='background:#1e293b;border:1px solid #334155;color:#94a3b8;font-size:18px;padding:6px 12px;border-radius:6px;cursor:pointer'>1:1</button>";
h+="<button onclick='zoomPhoto(0.2)' style='background:#1e293b;border:1px solid #334155;color:#94a3b8;font-size:18px;padding:6px 12px;border-radius:6px;cursor:pointer'>🔍+</button>";
h+="<span id=mb-zoom-level style='color:#94a3b8;font-size:14px;padding:4px 8px'>100%</span>";
h+="</div>";
h+="<div style='position:relative;display:flex;align-items:center;gap:8px'>";
h+="<button id=mb-prev-btn onclick=navigatePhoto('prev') style='background:#1e293b;border:1px solid #334155;color:#94a3b8;font-size:24px;padding:8px 14px;border-radius:6px;cursor:pointer'>◀</button>";
h+="<img id=mb-preview-img src='"+src+"' style='max-width:100%;max-height:400px;min-height:100px;min-width:100px;border-radius:8px;background:#0f172a' onerror=\"this.onerror=null;this.alt='No preview'\">";
h+="<div style='overflow:auto;max-width:100%;max-height:400px;border-radius:8px;background:#0f172a'>";
h+="<img id=mb-preview-img src='"+src+"' style='min-height:100px;min-width:100px;border-radius:8px;background:#0f172a;transform-origin:center center' onerror=\"this.onerror=null;this.alt='No preview'\">";
h+="</div>";
h+="<button id=mb-next-btn onclick=navigatePhoto('next') style='background:#1e293b;border:1px solid #334155;color:#94a3b8;font-size:24px;padding:8px 14px;border-radius:6px;cursor:pointer'>▶</button>";
h+="<span id=mb-photo-pos style='position:absolute;bottom:8px;right:50px;background:rgba(0,0,0,.7);color:#94a3b8;padding:2px 8px;border-radius:4px;font-size:11px'>1/1</span>";
h+="</div>";
h+="</div>";
}
h+="</div>";
b.innerHTML=h;
@@ -852,7 +864,27 @@ function closeDetail(){
}
// PHOTO NAVIGATION
var _photoUuid=null,_photoList=[];
var _photoUuid=null,_photoList=[],_photoZoom=1;
function zoomPhoto(delta){
var img=document.getElementById("mb-preview-img");
if(!img)return;
if(delta==0){
_photoZoom=1;
}else{
_photoZoom+=delta;
if(_photoZoom<0.2)_photoZoom=0.2;
if(_photoZoom>5)_photoZoom=5;
}
img.style.transform="scale("+_photoZoom+")";
img.style.maxWidth=_photoZoom>=1?"none":"100%";
img.style.maxHeight=_photoZoom>=1?"none":"400px";
var level=document.getElementById("mb-zoom-level");
if(level)level.textContent=Math.round(_photoZoom*100)+"%";
}
function setupPhotoNav(fuuid){
if(!_td) return;
@@ -882,8 +914,16 @@ function navigatePhoto(dir){
if(dir=="prev"&&idx>0)idx--;else if(dir=="next"&&idx<_photoList.length-1)idx++;
if(idx>=0&&idx<_photoList.length){
_photoUuid=_photoList[idx];
_photoZoom=1;
var img=document.getElementById("mb-preview-img");
if(img)img.src="/api/v2/files/"+userId+"/"+_photoUuid+"/stream?_="+Date.now();
if(img){
img.src="/api/v2/files/"+userId+"/"+_photoUuid+"/stream?_="+Date.now();
img.style.transform="scale(1)";
img.style.maxWidth="100%";
img.style.maxHeight="400px";
}
var level=document.getElementById("mb-zoom-level");
if(level)level.textContent="100%";
updatePhotoPos(_photoUuid);
}
}