自行实现图片预览功能

阅读 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

评论(0条)

(必填)
复制成功