站上的文章图片原来点了没反应,只有右键才能在新标签页打开。看着别扭,就想加个点击放大。
研究了一圈,发现有三条路,各有各的坑,记录一下。
方案一:装灯箱插件
搜一下 "WordPress 灯箱",能出来十几个。常用的有 Simple Lightbox、WP Lightbox 2、Responsive Lightbox。
装上就生效,不用改代码。听起来最省事,但实际有几个问题。
第一,体积大。
这些插件大多打包了完整的 jQuery 灯箱库,动辄几百 KB。站点本来就在为加载速度发愁,再加这些不合适。
第二,样式冲突。
插件的遮罩层和主题的弹窗经常打架,尤其是商城主题,z-index 一不小心就被压住。
第三,改不动。
想调个圆角、改个背景色,得去翻插件的 CSS 文件,改了升级还会被覆盖。
所以这条路直接放弃。
方案二:用 WordPress 自带的
WordPress 6.x 之后,图片块自带灯箱功能。
在编辑器里点图片,右侧设置栏里有一项 "点击时打开图片灯箱"(英文是 Expand on click),勾上就行。
用起来是这样的:图片右上角会出现一个半透明的小按钮,点按钮才放大,点图片本身没反应。
优点:零成本,不加载额外文件。
缺点:只对用图片块插入的图片生效。如果你用的是经典编辑器,或者图片是写在 HTML 里的,它管不着。
我站上的文章大部分是手动贴 HTML,所以这条也只覆盖了一部分。
方案三:自己写
最后选了这个。逻辑很简单:给正文里的每张图绑一个点击事件,点了就把图塞进一个全屏容器里显示。
全部代码不到 50 行,没有依赖,不加载任何外部库。
完整代码:
<style>
#lightbox{position:fixed;inset:0;z-index:999999;background:rgba(0,0,0,.93);
display:none;align-items:center;justify-content:center}
#lightbox.on{display:flex}
#lightbox img{max-width:92vw;max-height:88vh;display:block;border-radius:2px;
cursor:default;user-select:none}
#lightbox button{position:absolute;top:50%;transform:translateY(-50%);
width:52px;height:52px;border:0;border-radius:50%;background:rgba(255,255,255,.12);
color:#fff;font:24px/1 Arial;cursor:pointer}
#lightbox button:hover{background:rgba(255,255,255,.24)}
#lightbox .prev{left:24px}
#lightbox .next{right:24px}
#lightbox .num{position:absolute;bottom:22px;left:50%;transform:translateX(-50%);
color:rgba(255,255,255,.65);font-size:13px}
</style>
<script>
(function(){
var imgs = document.querySelectorAll('.post-content img');
var list = [];
Array.prototype.forEach.call(imgs, function(im){
var src = im.getAttribute('data-src') || im.getAttribute('src');
if (!src) return;
if (im.naturalWidth && im.naturalWidth < 120) return;
list.push(src);
im.style.cursor = 'zoom-in';
im.addEventListener('click', function(e){
e.preventDefault();
open(list.indexOf(src));
});
});
if (!list.length) return;
var box = document.createElement('div');
box.id = 'lightbox';
box.innerHTML = '<img alt="">'
+ '<button class="prev">‹</button>'
+ '<button class="next">›</button>'
+ '<span class="num"></span>';
document.body.appendChild(box);
var pic = box.querySelector('img');
var num = box.querySelector('.num');
var idx = 0;
function show(i){
idx = (i + list.length) % list.length;
pic.src = list[idx];
num.textContent = (idx + 1) + ' / ' + list.length;
}
function open(i){
show(i);
box.classList.add('on');
document.body.style.overflow = 'hidden';
}
function close(){
box.classList.remove('on');
pic.removeAttribute('src');
document.body.style.overflow = '';
}
box.querySelector('.prev').addEventListener('click', function(e){
e.stopPropagation(); show(idx - 1);
});
box.querySelector('.next').addEventListener('click', function(e){
e.stopPropagation(); show(idx + 1);
});
box.addEventListener('click', function(e){
if (e.target === box) close();
});
document.addEventListener('keydown', function(e){
if (!box.classList.contains('on')) return;
if (e.key === 'Escape') close();
if (e.key === 'ArrowLeft') show(idx - 1);
if (e.key === 'ArrowRight') show(idx + 1);
});
})();
</script>
三个必须注意的细节
一、排除小图。
文章里的图标、表情、徽章不需要放大。判断条件:
if (im.naturalWidth && im.naturalWidth < 120) return;
小于 120 像素的一律跳过。
二、处理懒加载。
很多主题给图片做了懒加载,真实地址在 data-src 里,src 只是个占位图。所以取地址要这么写:
var src = im.getAttribute('data-src') || im.getAttribute('src');
先找 data-src,没有再用 src。
三、和主题的事件冲突。
如果你用的主题自带 "点击图片下载" 功能,那点击会同时触发两件事:下载 + 打开灯箱。
解决办法是用捕获阶段绑定,并且在回调里阻止事件继续传播:
im.addEventListener('click', function(e){
e.preventDefault();
e.stopImmediatePropagation();
open(i);
}, true);
最后一个 true 是关键,表示在捕获阶段执行,会先于主题的冒泡监听器运行。
stopImmediatePropagation 会掐断同一元素上的后续所有监听器,主题那段下载代码就不会执行了。
还有一个 iOS 的坑
锁滚动的时候,只设 document.documentElement.style.overflow = 'hidden' 在 iOS Safari 上不管用,页面还能滚。
要两个都设:
document.documentElement.style.overflow = 'hidden';
document.body.style.overflow = 'hidden';
最后的效果
点图片全屏显示,左右按钮切换,底部显示 "2 / 6",点空白处或者按 ESC 关闭。
手机上左右滑动也能切换。
整个文件 5.7 KB,没有加载任何第三方库。
要功能的话,插件确实省事。但如果只是"点击看大图"这一个需求,自己写反而清爽,想怎么改就怎么改。
1、本站所有资源均收集于互联网,分享目的仅限学习与参考。如有侵权,请联系 1685698671@qq.com 及时删除!
2、本站资源不保证完整性和安全性,下载后请自行检测。使用过程中出现的任何问题均与本站无关,敬请自行处理。
3、本站资源仅限个人学习研究使用,严禁用于任何违法违纪用途。因使用者违规使用产生的一切后果,由使用者自行承担,本站不承担任何责任。


评论(0)