自行实现图片预览功能
阅读 2k
在Web应用中,图片预览是一个常见的功能,可以借助第三方库来实现(如viewer.js),但有时因为某些原因,需要自己实现。本篇将介绍在不使用第三方库的基础上,如何自行实现图片预览功能。
最终效果
为了更直观的说明,我们先看最终的效果,我放了一张示例图片,点击下方图片即可预览。
这个预览功能的特点如下:
- 带有淡入淡出的动画效果
- 精简,总共大约80行代码,大小只有2kb左右
我们来看看具体是怎么实现的吧。
框架:html
我们先来分析html部分,在预览图片时,需要一个遮罩层来突出显示当前图片,其基本结构如下:
<div class='viewer'>
<div class='container'>
<img />
</div>
</div>
接下来,我们再来看样式部分。
样式:css
对于遮罩层,为了让它完全铺满屏幕,通常会采用fixed布局,样式如下:
.viewer {
background: rgba(0, 0, 0, 0.85);
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;
}
对于其中的img标签,需要垂直居中
显示。同时,为了显示得优雅自然,需要让图片出现和消失时带有淡入淡出
的效果,所以需要对图片加上动画,代码如下:
img.in {
animation: fadeIn 0.2s;
}
img.out {
transform: scale(0);
animation: fadeOut 0.2s;
}
@keyframes fadeIn {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
@keyframes fadeOut {
from {
transform: scale(1);
}
to {
transform: scale(0);
}
}
因为img样式中使用了transform属性,所以,垂直居中时无法再使用transfrom的方式。于是决定在img标签上再套一层div标签,该div用flex布局:
.container {
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
}
最后,再加上鼠标提示效果,对需要预览的图片加上:
cursor: zoom-in;
对遮罩层的图片加上:
cursor: zoom-out;
这样,带有人性化的鼠标提示,淡入淡出效果的图片预览样式就确定好了。
逻辑:JavaScript
最后,我们再来解决逻辑部分,主要处理两件事情:
- 给需要预览的图片加上事件,当点击时,将该图片的src赋值给遮罩层上的img标签,同时将遮罩层的样式改为
display:block
。 - 给遮罩层添加事件,当不需要预览时,点击图片或者遮罩层,关闭遮罩层预览界面。
完整的代码如下:
const articleDOM = document.querySelector('#article article')
const viewerDOM = document.querySelector('#app>.viewer')
const zoomImgDOM = viewerDOM.querySelector('img')
articleDOM.onclick = async function (e) {
const { nodeName, src } = e.target
if (nodeName !== 'IMG') return
const actualWidth = await getImgSize(src)
zoomImgDOM.src = src;
zoomImgDOM.className = 'in'
zoomImgDOM.style.width = `${actualWidth}px`
viewerDOM.style.display = 'block';
document.body.style.overflow = 'hidden'
}
viewerDOM.onclick = function () {
zoomImgDOM.className = 'out'
setTimeout(() => {
viewerDOM.style.display = 'none'
document.body.style.overflow = 'auto'
}, 300)
}
在遮罩层显示的时候,如果用户滚动,会导致整个页面也滚动,所以需要在预览时禁止页面滚动。需要在body上加上样式overflow: hidden
。
另外,我们还需要获得图片的实际宽度:
function getImgSize(src) {
const img = new Image()
img.src = src
return new Promise((resolve, reject) => {
img.onload = () => resolve(img.width)
})
}
整个逻辑部分并不复杂,只有大约30行代码。
小结
全部代码,只有大约80行,没有借助任何第三方库,就实现了图片预览的功能,这并不是什么难事,把一些细节处理好就可以了。
最后编辑于: 2022-06-24