记录--手把手教学,实现一个优雅的图片预览
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
在我们开发项目中,经常会遇到预览图片的需求。也就是点击图片,会全屏显示该图片。需求很简单,但是如何让实现更优雅就需要花点心思了。
最终效果图
基础版本
实现方式
- 点击图片,创建蒙层,克隆图片
- 将图片添加定位属性,并添加到蒙层中
- 将蒙层添加到body中
观察下图发现,虽然实现了需求,但是动画很生硬,我们作为前端开发工程师,得对得起工程师
的身份,需要有工匠精神,接下来将介绍如何实现优雅的图片预览效果。
效果图
代码
<!DOCTYPE html> <html lang="en"> <head> <title>基础版本</title> <style> .pic1 { width: 400px; } .mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.7); } .previewImg { position: absolute; width: 80%; left: 50%; top: 200px; transform: translateX(-50%); } </style> </head> <body> <img class="pic1" src="./xtjj.jpg" alt=""> <script> const pic1 = document.querySelector(".pic1"); pic1.addEventListener("click", function () { // 创建蒙层 const mask = document.createElement("div") mask.classList.add("mask"); const pic1Clone = pic1.cloneNode(); pic1Clone.classList.add("previewImg"); // 将图片和蒙层添加到页面中 mask.appendChild(pic1Clone) document.body.appendChild(mask) mask.addEventListener("click", function () { document.body.removeChild(this) }) }) </script> </body> </html>
打开动画
实现方式
- 点击图片
- 克隆原图,计算原图当前距离窗口的top与left的距离(用于确定克隆图片的初始位置)
- 计算克隆图片的初始位置以及其相关属性
- 创建蒙层,并添加相关的定位,背景色属性
- 使用
setTimeout
是为了触发transition
,产生移动效果。 - 并且在
setTimeout
最开始将原图进行隐藏,产生是原图移动到屏幕中心的效果。使用visibility
属性,避免引起页面布局变化。
- 为蒙层添加点击事件
- 点击蒙层后,删除蒙层元素,实现关闭预览功能
效果图
代码
<!DOCTYPE html> <html lang="en"> <head> <title>添加预览动画</title> <style> .pic { width: 400px; } .mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.7); transition: all .3s; } .previewImg { position: absolute; transform: translateX(-50%); transition: all .3s; } </style> </head> <body> <img class="pic" src="./xtjj.jpg" alt=""> <script> const pic = document.querySelector(".pic"); pic.addEventListener("click", function () { // 1,克隆元素 const pic2 = pic.cloneNode(); // 2,计算原图距离窗口left,top的距离 picToTop = pic.getBoundingClientRect().x; picToLeft = pic.getBoundingClientRect().y; // 3,设置克隆图片初始位置 pic2.style.position = "absolute"; pic2.style.left = `${picToLeft}px`; pic2.style.top = `${picToTop}px`; // 4,创建蒙层 const mask = document.createElement("div") mask.classList.add("mask"); // 5,将元素添加到body中 mask.appendChild(pic2) document.body.appendChild(mask) // 6,使用setTimeout是为了触发`transition`,产生动画 setTimeout(() => { // 7,隐藏原图片 pic.style.visibility = "hidden"; // 8,设置预览图片展示宽度以及位置 pic2.style.width = "80%"; pic2.style.left = "50%"; pic2.style.top = `200px`; pic2.classList.add("previewImg"); }, 0); // 9,点击蒙层关闭预览 mask.addEventListener("click", function () { this.remove() }) }) </script> </body> </html>
关闭动画
上一个步骤中,实现了点击图片,图片流畅显示的动画。但是关闭的时候很突然,这次将实现关闭的流畅动画。
实现方式
- 点击图片的时候获取原图的
宽度
,以及距离窗口left
,top
的距离 - 点击蒙层的时候将克隆图片的位置移动到原图的位置(根据前面获取的原图位置)
- 当克隆图片回到原图的位置时,需要将原图进行显示。使用
visibility
属性。 - 使用
setTimeout
的原因是触发transition
,产生动画效果。 - 使用300毫秒是因为
transition
设置的是300毫秒的过渡时间,为了能在克隆图片会到原图位置的时候,再显示原图,并删除蒙层。
效果图
代码
查看下个步骤
滚动时取消预览
实现方式
-
在点击图片的时候,存储当前页面滚动的距离:
lastPositon
-
监听滚动事件,当滚动的距离减去
lastPositon
的值,大于100px
的时候,触发蒙层的点击事件 -
蒙层收到点击动作后,会执行取消预览的一系列动作。
完整代码
<!DOCTYPE html> <html lang="en"> <head> <title>滚动时取消预览</title> <style> body { height: 1000px; } .pic { width: 400px; } .mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.7); transition: all .3s; } </style> </head> <body> <img class="pic" src="./xtjj.jpg" alt=""> <script> // 16,滚动超过100px。就取消预览 window.onscroll = (e) => { if (Math.abs(window.pageYOffset - lastPositon) > 100) { document.querySelector(".mask")?.click(); } } // 14,预览图片前页面滚动距离初始值 let lastPositon = 0; const pic = document.querySelector(".pic"); pic.addEventListener("click", function () { // 15,计算预览图片前页面滚动距离 lastPositon = window.pageYOffset; // 1,克隆元素 const pic2 = pic.cloneNode(); // 2,计算原图距离窗口left,top的距离 picToTop = pic.getBoundingClientRect().x; picToLeft = pic.getBoundingClientRect().y; // 11,计算原图宽度 picWidth = pic.width; // 3,设置克隆图片初始位置 pic2.style.position = "absolute"; pic2.style.left = `${picToLeft}px`; pic2.style.top = `${picToTop}px`; // 4,创建蒙层 const mask = document.createElement("div") mask.classList.add("mask"); // 5,将元素添加到body中 mask.appendChild(pic2) document.body.appendChild(mask) // 6,使用setTimeout是为了触发`transition`,产生动画 setTimeout(() => { // 7,隐藏原图片 pic.style.visibility = "hidden"; // 8,设置预览图片展示宽度以及位置 pic2.style.position = "absolute"; pic2.style.transition = "all .3s"; pic2.style.transform = "translateX(-50%)"; pic2.style.width = "80%"; pic2.style.left = "50%"; pic2.style.top = `200px`; }, 0); // 9,点击蒙层关闭预览 mask.addEventListener("click", function () { // 10,预览图回到原图位置 pic2.style.width = `${picWidth}px`; pic2.style.left = `${picToLeft}px`; pic2.style.top = `${picToTop}px`; pic2.style.transform = ""; // 12,显示原图 setTimeout(() => { pic.style.visibility = "visible"; // 13,删除蒙层以及预览图 this.remove() }, 300); }) }) </script> </body> </html>