五站研究(PhotoSwipe 源码级核对/medium-zoom/Unsplash◐/图虫◐/Flickr) → 六维差距 → v2.1 增强提案十项(P0=原位起飞开合+背景点击关;P1= chrome 双层淡入/相邻预载/双指缩放;P2=换片过渡/缩放指示/长图侧置 meta/HD 交换/竖拖关闭)+ 明确不做清单八条 + 可交互单文件 mockup (仓内实拍 5 张、13 项交互可点)。 验证: mockup 引用路径 ../content/photos/ 相对仓根可开;文档引文对 PhotoSwipe defaultOptions 源码核对注记 Spec: none (研究文档+设计预览稿,v2.1 立项待用户拍板) Co-authored-by: GLM-5.3
311 lines
17 KiB
HTML
311 lines
17 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>灯箱 v2.1 提案预览 · wait4x</title>
|
||
<style>
|
||
/* ===== 灰阶基底(对齐站 tokens.css:四档灰 + 唯一曲线族) ===== */
|
||
:root{
|
||
--bg:#fff; --bg-soft:#f7f7f8; --ink-1:#111113; --ink-2:#33343a; --ink-3:#6b6e78;
|
||
--ink-4:#a0a3ad; --line:#e6e7eb; --radius-img:10px;
|
||
--mono:"JetBrains Mono",ui-monospace,Consolas,monospace;
|
||
--sans:"Noto Sans SC Variable","Noto Sans SC",system-ui,-apple-system,"PingFang SC",sans-serif;
|
||
--ez:cubic-bezier(.4,0,.22,1); /* PhotoSwipe 333ms 节奏同族曲线 */
|
||
}
|
||
*{box-sizing:border-box}
|
||
body{margin:0;background:var(--bg);color:var(--ink-2);font-family:var(--sans);}
|
||
body.locked{overflow:hidden}
|
||
.wrap{max-width:896px;margin:0 auto;padding:28px 20px 72px}
|
||
kbd{font-family:var(--mono);font-size:11.5px;border:1px solid var(--line);background:#fff;
|
||
border-radius:4px;padding:1px 6px;color:var(--ink-3)}
|
||
|
||
/* ===== 顶部说明:这是提案预览稿 ===== */
|
||
.note{background:var(--bg-soft);border:1px solid var(--line);border-radius:10px;
|
||
padding:14px 18px;font-size:13.5px;line-height:1.7;color:var(--ink-2);margin:18px 0 30px}
|
||
.note strong{color:var(--ink-1)}
|
||
.note ul{margin:6px 0 0;padding-left:18px}
|
||
.note li{margin:2px 0}
|
||
h1{font-size:27px;color:var(--ink-1);margin:8px 0 2px;font-weight:600}
|
||
.sub{font-family:var(--mono);font-size:12.5px;color:var(--ink-4)}
|
||
|
||
/* ===== 影像墙:cover 裁切(与线上一致,起飞动画的前提) ===== */
|
||
.stage{background:rgba(255,255,255,.04);border-radius:6px;padding:14px}
|
||
.wall{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(3,1fr);
|
||
grid-auto-rows:8px;grid-auto-flow:dense;gap:14px}
|
||
.shot{position:relative;overflow:hidden;border-radius:var(--radius-img);grid-row-end:span var(--sp,13)}
|
||
.shot button{display:block;width:100%;height:100%;padding:0;border:none;background:none;cursor:zoom-in}
|
||
.shot img{display:block;width:100%;height:100%;object-fit:cover}
|
||
@media (max-width:820px){.wall{grid-template-columns:repeat(2,1fr)}}
|
||
@media (max-width:560px){.wall{grid-template-columns:1fr 1fr;gap:10px}}
|
||
|
||
/* ===== 灯箱:fixed 覆盖层(生产将等价几何搬回原生 <dialog>) ===== */
|
||
.lbx{position:fixed;inset:0;z-index:80}
|
||
.lbx[hidden]{display:none}
|
||
.lbx-bg{position:absolute;inset:0;background:rgba(8,10,14,.96);opacity:0;
|
||
transition:opacity 300ms var(--ez)}
|
||
.lbx.on .lbx-bg{opacity:1}
|
||
/* 双盒:win=裁切窗(动画 left/top/w/h),pic=内图(动画几何 + 缩放 transform) */
|
||
.lbx-win{position:fixed;overflow:hidden;border-radius:6px;transform-origin:0 0;
|
||
box-shadow:0 12px 48px rgba(0,0,0,.5);touch-action:none}
|
||
.lbx-pic{position:absolute;transform-origin:50% 50%;user-select:none;-webkit-user-drag:none;
|
||
transition:transform 90ms linear;cursor:zoom-in;display:block}
|
||
.lbx.landing .lbx-win,.lbx.landing .lbx-pic{
|
||
transition:left 300ms var(--ez),top 300ms var(--ez),width 300ms var(--ez),
|
||
height 300ms var(--ez),transform 300ms var(--ez),opacity 300ms var(--ez)}
|
||
.lbx-pic.zoomed{cursor:grab}.lbx-pic.grabbing{cursor:grabbing}
|
||
.lbx-pic.swap{opacity:0}
|
||
|
||
/* chrome 层 1:关闭/箭头/计数(+140ms 淡入) */
|
||
.c1{opacity:0;transition:opacity 220ms var(--ez)}
|
||
.lbx.on .c1{opacity:1;transition-delay:140ms}
|
||
.lbx-btn{position:fixed;width:44px;height:44px;border-radius:10px;cursor:pointer;
|
||
border:1px solid rgba(255,255,255,.22);background:rgba(20,24,30,.55);color:#e6e9ee;
|
||
backdrop-filter:blur(4px);box-shadow:0 2px 10px rgba(0,0,0,.35);display:grid;place-items:center}
|
||
.lbx-btn:hover{background:rgba(255,255,255,.12)}
|
||
.lbx-close{top:16px;right:16px}
|
||
.lbx-prev{left:14px;top:50%;translate:0 -50%}
|
||
.lbx-next{right:14px;top:50%;translate:0 -50%}
|
||
.lbx-count{position:fixed;top:26px;left:20px;font-family:var(--mono);font-size:12.5px;color:#98a2b3}
|
||
|
||
/* chrome 层 2:caption / title+EXIF / 动作(+300ms 淡入) */
|
||
.c2{opacity:0;transition:opacity 260ms var(--ez)}
|
||
.lbx.on .c2{opacity:1;transition-delay:300ms}
|
||
.lbx-meta{position:fixed;left:0;right:0;bottom:0;display:flex;flex-direction:column;align-items:center;
|
||
gap:3px;padding:14px 72px 20px;text-align:center;text-shadow:0 1px 4px rgba(0,0,0,.6)}
|
||
.lbx-caption{margin:0;font-family:var(--sans);font-size:13.5px;line-height:1.6;color:#dfe6f3;max-width:640px}
|
||
.lbx-row{display:flex;align-items:center;flex-wrap:wrap;justify-content:center;gap:14px;
|
||
font-family:var(--mono);font-size:12.5px}
|
||
.lbx-title{color:#fff;font-family:var(--sans);font-size:13px;font-weight:600}
|
||
.lbx-exif{color:#98a2b3}
|
||
.lbx-acts{display:inline-flex;gap:10px}
|
||
.lbx-act{display:inline-flex;align-items:center;gap:5px;padding:6px 11px;border-radius:10px;
|
||
border:1px solid rgba(255,255,255,.22);background:rgba(20,24,30,.55);color:#dfe6f3;
|
||
font-family:var(--mono);font-size:12px;text-decoration:none;backdrop-filter:blur(4px)}
|
||
.lbx-act:hover{background:rgba(40,48,60,.75);color:#fff}
|
||
|
||
/* 沉浸态:zoom>1 或按 i —— chrome 全隐,舞台纯净 */
|
||
.lbx.clean .c1,.lbx.clean .c2,.lbx.noui .c1,.lbx.noui .c2{opacity:0;transition-delay:0ms}
|
||
|
||
/* 首开提示 + 缩放指示 */
|
||
.lbx-hint{position:fixed;left:50%;bottom:128px;translate:-50% 0;padding:7px 13px;border-radius:10px;
|
||
border:1px solid rgba(255,255,255,.22);background:rgba(20,24,30,.55);backdrop-filter:blur(4px);
|
||
font-family:var(--mono);font-size:12px;color:#dfe6f3;opacity:0;transition:opacity 400ms var(--ez);
|
||
pointer-events:none}
|
||
.lbx-hint.show{opacity:1}
|
||
.lbx-zind{position:fixed;right:20px;bottom:128px;font-family:var(--mono);font-size:12px;color:#98a2b3;
|
||
opacity:0;transition:opacity 300ms var(--ez);pointer-events:none}
|
||
.lbx-zind.show{opacity:1}
|
||
|
||
@media (max-width:560px){
|
||
.lbx-prev{left:6px}.lbx-next{right:6px}
|
||
.lbx-meta{padding:12px 16px 16px}
|
||
.lbx-hint{bottom:150px}
|
||
}
|
||
@media (prefers-reduced-motion:reduce){
|
||
.lbx-bg,.c1,.c2,.lbx-pic,.lbx-win,.lbx-hint,.lbx-zind{transition:none!important}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<h1>图库 · 灯箱 v2.1 提案预览</h1>
|
||
<p class="sub">预览稿 —— 交互为提案演示(非线上行为)· 图片为 content/photos 实拍,EXIF 为示例数据</p>
|
||
<div class="note">
|
||
<strong>这是给浏览器直接打开的交互演示</strong>,对应《09-灯箱美化探索》提案 #1/#2/#3/#6/#7:
|
||
<ul>
|
||
<li><strong>原位起飞开合</strong>:点击缩略图,照片从原位放大入舞台;关闭回落原位(<kbd>Esc</kbd> / 背景点击 / 关闭钮)</li>
|
||
<li><strong>chrome 双层淡入</strong>:开箱后层 1(箭头/计数)先入、层 2(caption/EXIF)随入;<kbd>i</kbd> 隐藏全部;放大后自动隐层</li>
|
||
<li><strong>连拍导航</strong>:<kbd>←</kbd> <kbd>→</kbd> / 边缘箭头 / 触屏快滑;计数 n / N</li>
|
||
<li><strong>缩放</strong>:滚轮锚点缩放 1–4x、<kbd>双击</kbd> 1x↔2.5x、放大后拖拽、双指缩放;右下角缩放指示</li>
|
||
</ul>
|
||
</div>
|
||
<div class="stage"><ul class="wall" id="wall"></ul></div>
|
||
</div>
|
||
|
||
<!-- 灯箱:fixed 覆盖层(生产等价搬回原生 <dialog>,focus-trap 由 dialog 免费提供) -->
|
||
<div class="lbx" id="lbx" hidden>
|
||
<div class="lbx-bg"></div>
|
||
<div class="lbx-win" id="win"><img class="lbx-pic" id="pic" alt=""></div>
|
||
<button class="lbx-btn lbx-close c1" id="bClose" aria-label="关闭(Esc)">
|
||
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="m5 5 14 14M19 5 5 19"/></svg></button>
|
||
<button class="lbx-btn lbx-prev c1" id="bPrev" aria-label="上一张(←)">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m14.5 5.5-6.5 6.5 6.5 6.5"/></svg></button>
|
||
<button class="lbx-btn lbx-next c1" id="bNext" aria-label="下一张(→)">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9.5 5.5 6.5 6.5-6.5 6.5"/></svg></button>
|
||
<div class="lbx-count c1" id="count">1 / 5</div>
|
||
<div class="lbx-meta c2">
|
||
<p class="lbx-caption" id="cap"></p>
|
||
<div class="lbx-row"><strong class="lbx-title" id="ttl"></strong><span class="lbx-exif" id="exif"></span>
|
||
<span class="lbx-acts"><a class="lbx-act" id="aOrig" href="#" target="_blank" rel="noopener">原图 ↗</a><a class="lbx-act" id="aDl" href="#" download>下载 ↓</a></span></div>
|
||
</div>
|
||
<div class="lbx-hint" id="hint">滚轮缩放 · 双击放大 · Esc 关闭 · i 隐藏界面</div>
|
||
<div class="lbx-zind" id="zind">100%</div>
|
||
</div>
|
||
|
||
<script>
|
||
/* ===== 数据:仓内实拍(含 2.36:1 长横幅与 2:3 竖图两种 letterbox 形态) ===== */
|
||
const PHOTOS=[
|
||
{src:'../content/photos/1766156983093.jpg',w:2400,h:1600,sp:13,title:'防波堤暮色',
|
||
cap:'落日把海与城一齐烫成金箔,海鸟的剪影恰好掠过日轮',exif:'X-T5 · XF35mmF1.4 · f/5.6 · 1/500s · ISO 200'},
|
||
{src:'../content/photos/mmexport1771816382115.jpg',w:2400,h:1018,sp:6,title:'长滩低云',
|
||
cap:'涨潮前的长滩,云层压得很低',exif:'X100VI · f/8 · 1/1000s · ISO 160'},
|
||
{src:'../content/photos/1766156998344.jpg',w:1600,h:2400,sp:20,title:'旗与塔',
|
||
cap:'旗在风里翻卷,塔身亮得像一支随时点火的火箭',exif:'GR III · f/2.8 · 1/250s · ISO 400'},
|
||
{src:'../content/photos/1766157004116.jpg',w:2400,h:1536,sp:9,title:'暮色撤离',
|
||
cap:'灯柱次第亮起,暮色像退潮一样撤离',exif:'X-T5 · XF56mmF1.2 · f/1.4 · 1/120s · ISO 800'},
|
||
{src:'../content/photos/mmexport1776564092433.jpg',w:2400,h:1600,sp:13,title:'夜航',
|
||
cap:'货轮的灯在雾里连成一条迟疑的线',exif:'X-T5 · XF70-300mm · f/4 · 1/60s · ISO 1250'}];
|
||
const N=PHOTOS.length;
|
||
|
||
const $=id=>document.getElementById(id);
|
||
const lbx=$('lbx'),win=$('win'),pic=$('pic'),wall=$('wall');
|
||
const reduced=matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||
let idx=0,open_=false,hintShown=false;
|
||
let zoom={s:1,tx:0,ty:0};
|
||
|
||
/* ===== 影像墙 ===== */
|
||
PHOTOS.forEach((p,i)=>{
|
||
const li=document.createElement('li');
|
||
li.className='shot'; li.style.setProperty('--sp',p.sp);
|
||
const b=document.createElement('button'); b.type='button'; b.setAttribute('aria-label',p.title);
|
||
b.dataset.i=i;
|
||
const im=document.createElement('img'); im.src=p.src; im.alt=p.title; im.loading=i<3?'eager':'lazy';
|
||
b.appendChild(im); li.appendChild(b); wall.appendChild(li);
|
||
b.addEventListener('click',()=>openLbx(i));
|
||
});
|
||
const thumbImg=i=>wall.querySelector(`button[data-i="${i}"] img`);
|
||
|
||
/* ===== 几何:舞台 fit 矩形 / cover-contain 双盒(PhotoSwipe data-cropped 路线) ===== */
|
||
function stageBox(){const W=innerWidth,H=innerHeight;
|
||
const side=W>760?56:12,top=64,bot=innerWidth>560?124:150;
|
||
return{x:side,y:top,w:W-side*2,h:H-top-bot};}
|
||
function fitRect(p,box){const r=p.w/p.h,br=box.w/box.h;let w,h;
|
||
if(r>br){w=box.w;h=w/r;}else{h=box.h;w=h*r;}
|
||
return{x:box.x+(box.w-w)/2,y:box.y+(box.h-h)/2,w,h};}
|
||
function coverIn(p,winR){const r=p.w/p.h,wr=winR.w/winR.h;let w,h;
|
||
if(wr>r){h=winR.h;w=h*r;}else{w=winR.w;h=w/r;}
|
||
return{x:(winR.w-w)/2,y:(winR.h-h)/2,w,h};} /* 相对 win 的坐标 */
|
||
const setBox=(el,g)=>{el.style.left=g.x+'px';el.style.top=g.y+'px';
|
||
el.style.width=g.w+'px';el.style.height=g.h+'px';};
|
||
|
||
/* ===== 开箱:从缩略图原位起飞 ===== */
|
||
function fillMeta(p){$('cap').textContent=p.cap;$('ttl').textContent=p.title;
|
||
$('exif').textContent=p.exif;$('count').textContent=`${idx+1} / ${N}`;
|
||
$('aOrig').href=p.src;$('aDl').href=p.src;$('aDl').setAttribute('download',p.title+'.jpg');}
|
||
function openLbx(i){
|
||
idx=i;const p=PHOTOS[idx];pic.src=p.src;pic.alt=p.title;fillMeta(p);
|
||
const t=thumbImg(i).getBoundingClientRect();
|
||
const tr=fitRect(p,stageBox());
|
||
zoom={s:1,tx:0,ty:0};pic.style.transform='none';pic.classList.remove('zoomed','grabbing','swap');
|
||
lbx.hidden=false;open_=true;document.body.classList.add('locked');
|
||
lbx.classList.add('landing');
|
||
setBox(win,t);setBox(pic,coverIn(p,t)); /* 起点:与缩略图逐像素同框(cover 裁切) */
|
||
if(reduced){lbx.classList.add('on');lbx.classList.remove('landing');setBox(win,tr);setBox(pic,{x:0,y:0,w:tr.w,h:tr.h});}
|
||
else{
|
||
void win.offsetWidth; /* 强制 reflow,起点先落定 */
|
||
lbx.classList.add('on');
|
||
setBox(win,tr);setBox(pic,{x:0,y:0,w:tr.w,h:tr.h}); /* 终点:舞台 contain */
|
||
setTimeout(()=>lbx.classList.remove('landing'),330);
|
||
}
|
||
if(!hintShown){hintShown=true;const h=$('hint');h.classList.add('show');
|
||
setTimeout(()=>h.classList.remove('show'),2600);}
|
||
}
|
||
|
||
/* ===== 关闭:回落到缩略图原位 ===== */
|
||
function closeLbx(){
|
||
if(!open_)return;
|
||
const p=PHOTOS[idx],t=thumbImg(idx)?.getBoundingClientRect();
|
||
instantResetZoom();
|
||
if(reduced||!t){lbx.hidden=true;lbx.classList.remove('on','clean','noui');open_=false;
|
||
document.body.classList.remove('locked');return;}
|
||
lbx.classList.add('landing');
|
||
setBox(win,t);setBox(pic,coverIn(p,t));
|
||
lbx.classList.remove('on','clean','noui');
|
||
setTimeout(()=>{lbx.hidden=true;lbx.classList.remove('landing');open_=false;
|
||
document.body.classList.remove('locked');},320);
|
||
}
|
||
|
||
/* ===== 换片:旧图淡出、新图自侧向 10% 淡入(spacing 节奏) ===== */
|
||
function show(i,dir){
|
||
idx=((i%N)+N)%N;const p=PHOTOS[idx];instantResetZoom();fillMeta(p);
|
||
pic.src=p.src;pic.alt=p.title;
|
||
const tr=fitRect(p,stageBox());setBox(win,tr);setBox(pic,{x:0,y:0,w:tr.w,h:tr.h});
|
||
if(!reduced){pic.classList.add('swap');
|
||
pic.style.transform=`translateX(${dir*-10}%)`;
|
||
void pic.offsetWidth;pic.classList.remove('swap');
|
||
pic.style.transform='none';}
|
||
}
|
||
|
||
/* ===== 缩放:滚轮锚点 / 双击 / 双指 / 拖拽(复用线上 v2 数学) ===== */
|
||
function applyZoom(){pic.style.transform=`translate(${zoom.tx}px,${zoom.ty}px) scale(${zoom.s})`;
|
||
pic.classList.toggle('zoomed',zoom.s!==1);
|
||
lbx.classList.toggle('clean',zoom.s!==1);}
|
||
function instantResetZoom(){const keep=pic.style.transition;pic.style.transition='none';
|
||
zoom={s:1,tx:0,ty:0};pic.style.transform='none';pic.classList.remove('zoomed');
|
||
lbx.classList.remove('clean');void pic.offsetWidth;pic.style.transition=keep||'';}
|
||
function zoomAt(next,cx,cy){const r=pic.getBoundingClientRect();
|
||
const ax=cx-r.left-r.width/2-zoom.tx,ay=cy-r.top-r.height/2-zoom.ty;
|
||
const k=next/zoom.s;zoom.tx-=ax*(k-1);zoom.ty-=ay*(k-1);zoom.s=next;applyZoom();zindShow();}
|
||
let zt;function zindShow(){const z=$('zind');z.textContent=Math.round(zoom.s*100)+'%';
|
||
z.classList.add('show');clearTimeout(zt);zt=setTimeout(()=>z.classList.remove('show'),900);}
|
||
lbx.addEventListener('wheel',e=>{if(!open_)return;e.preventDefault();
|
||
const f=Math.exp(-e.deltaY*0.0015);
|
||
const next=Math.min(4,Math.max(1,zoom.s*f));
|
||
if(next!==zoom.s)zoomAt(next,e.clientX,e.clientY);},{passive:false});
|
||
win.addEventListener('dblclick',e=>{if(zoom.s===1)zoomAt(2.5,e.clientX,e.clientY);
|
||
else instantResetZoom();}); /* 挂 win:放大态 setPointerCapture 会把 click 派发给 win,pic 收不到 */
|
||
|
||
/* 拖拽平移(放大态)+ 双指缩放:pointer 事件统一 */
|
||
const pts=new Map();let drag=null,pinch=null;
|
||
win.addEventListener('pointerdown',e=>{
|
||
pts.set(e.pointerId,{x:e.clientX,y:e.clientY});
|
||
if(pts.size===2){const a=[...pts.values()];
|
||
pinch={d0:Math.hypot(a[0].x-a[1].x,a[0].y-a[1].y),s0:zoom.s,
|
||
mx:(a[0].x+a[1].x)/2,my:(a[0].y+a[1].y)/2};drag=null;return;}
|
||
if(zoom.s>1){win.setPointerCapture(e.pointerId);
|
||
drag={x:e.clientX,y:e.clientY,tx:zoom.tx,ty:zoom.ty};pic.classList.add('grabbing');}
|
||
});
|
||
win.addEventListener('pointermove',e=>{
|
||
if(pts.has(e.pointerId))pts.set(e.pointerId,{x:e.clientX,y:e.clientY});
|
||
if(pinch&&pts.size===2){const a=[...pts.values()];
|
||
const d=Math.hypot(a[0].x-a[1].x,a[0].y-a[1].y);
|
||
const next=Math.min(4,Math.max(1,pinch.s0*d/pinch.d0));
|
||
if(next!==zoom.s)zoomAt(next,pinch.mx,pinch.my);return;}
|
||
if(drag){zoom.tx=drag.tx+e.clientX-drag.x;zoom.ty=drag.ty+e.clientY-drag.y;applyZoom();}
|
||
});
|
||
const endPt=e=>{pts.delete(e.pointerId);if(pts.size<2)pinch=null;
|
||
if(drag){drag=null;pic.classList.remove('grabbing');}};
|
||
win.addEventListener('pointerup',endPt);win.addEventListener('pointercancel',endPt);
|
||
|
||
/* 触屏快滑翻页(zoom=1 时) */
|
||
let x0=null;lbx.addEventListener('touchstart',e=>{x0=e.touches[0].clientX;},{passive:true});
|
||
lbx.addEventListener('touchend',e=>{if(x0===null||zoom.s!==1){x0=null;return;}
|
||
const dx=e.changedTouches[0].clientX-x0;
|
||
if(Math.abs(dx)>40)show(idx+(dx<0?1:-1),dx<0?1:-1);x0=null;},{passive:true});
|
||
|
||
/* ===== 键盘 / 背景点击 / chrome 召唤 ===== */
|
||
document.addEventListener('keydown',e=>{
|
||
if(!open_)return;
|
||
if(e.key==='Escape')closeLbx();
|
||
else if(e.key==='ArrowLeft')show(idx-1,-1);
|
||
else if(e.key==='ArrowRight')show(idx+1,1);
|
||
else if(e.key==='i'||e.key==='I')lbx.classList.toggle('noui');
|
||
});
|
||
lbx.addEventListener('click',e=>{
|
||
if(e.target.closest('.lbx-win')||e.target.closest('.lbx-btn')||
|
||
e.target.closest('.lbx-meta')||e.target.closest('a'))return;
|
||
closeLbx(); /* 背景点击关闭(bgClickAction:'close' 同款) */
|
||
});
|
||
$('bClose').addEventListener('click',closeLbx);
|
||
$('bPrev').addEventListener('click',()=>show(idx-1,-1));
|
||
$('bNext').addEventListener('click',()=>show(idx+1,1));
|
||
|
||
/* 开箱中窗口变化:舞台即时重排(不做动画,避免与缩放打架) */
|
||
addEventListener('resize',()=>{if(!open_||lbx.classList.contains('landing'))return;
|
||
const p=PHOTOS[idx];const tr=fitRect(p,stageBox());
|
||
setBox(win,tr);setBox(pic,{x:0,y:0,w:tr.w,h:tr.h});});
|
||
</script>
|
||
</body>
|
||
</html>
|