目录
一、需求描述
前端实现放大镜效果;
- 鼠标移入图片区域,显示遮罩层;
- 鼠标移出图片区域,隐藏遮罩层;
- 鼠标移动,遮罩层跟随鼠标移动;
- 遮罩层不能超出图片所在区域;
- 遮罩层覆盖的图片区域按照指定比例放大显示;
- 遮罩层移动,放大图跟随移动;
二、实现效果
初始效果
放大效果
三、完整代码
【test.html】
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>放大镜效果</title> <style> * { margin: 0; padding: 0; } .one-img-box, .big-img-box { position: relative; width: 300px; height: 300px; box-shadow: 0 0 6px 1px #cacaca; border-radius: 10px; overflow: hidden; } .one-img-box { display: inline-block; top: 60px; left: 60px; cursor: move; } .one-img-box>img { width: 100%; height: 100%; } .big-img-box { /* display: inline-block; */ display: none; top: 60px; left: 100px; } .big-img-box>img { width: 300%; height: 300%; } .big-img { position: absolute; left: 0; top: 0; } .mask { /* display: inline-block; */ display: none; position: absolute; left: 0; top: 0; width: 100px; height: 100px; background-color: yellowgreen; opacity: .4; } </style> </head> <body> <div class="one-img-box"> <img src="D:\test\girl.png" alt=""> <div class="mask"></div> </div> <div class="big-img-box"><img class="big-img" src="D:\test\girl.png" alt=""></div> </body> <script> // 1、获取元素 // 获取原图的盒子 var oneImgBox = document.querySelector('.one-img-box'); // 获取遮罩层 var mask = document.querySelector('.mask'); // 获取大图盒子 var bigImgBox = document.querySelector('.big-img-box'); // 获取大图 var bigImg = document.querySelector('.big-img'); // 2、控制显示与隐藏 // 2.1 鼠标经过 oneImgBox,显示 mask遮挡层 和 bigImgBox大盒子; oneImgBox.addEventListener('mouseover', function () { mask.style.display = 'inline-block'; bigImgBox.style.display = 'inline-block'; }) // 2.2 鼠标移出 oneImgBox,隐藏 mask遮挡层 和 bigImgBox大盒子; oneImgBox.addEventListener('mouseout', function () { mask.style.display = 'none'; bigImgBox.style.display = 'none'; }) // 3、遮罩层跟随鼠标移动 oneImgBox.addEventListener('mousemove', function (e) { // 3.1 计算鼠标在盒子内的坐标 var mouseX = e.pageX - oneImgBox.offsetLeft; var mouseY = e.pageY - oneImgBox.offsetTop; // 3.2 计算遮罩层的移动位置 // 移动位置 = 鼠标的移动距离 - 遮罩层自己宽度\高度的一半(鼠标会在遮罩层中心位置,否则在左上角) var maskX = mouseX - mask.offsetWidth / 2; var maskY = mouseY - mask.offsetWidth / 2; // 计算结果赋给遮罩层; // mask.style.left = maskX + 'px'; // mask.style.top = maskY + 'px'; // 4、控制遮罩层的移动范围 // 4.1 计算遮罩层最大移动宽度\高度 = 原图盒子的宽度\高度 - 遮罩层的宽度\高度 var maskMaxX = oneImgBox.offsetWidth - mask.offsetWidth; var maskMaxY = oneImgBox.offsetHeight - mask.offsetHeight // 如果移动距离 大于 最大移动距离,则取最大的移动距离 // 如果移动距离 小于 0,则取0; maskX = maskX > maskMaxX ? maskMaxX : maskX < 0 ? 0 : maskX; maskY = maskY > maskMaxY ? maskMaxY : maskY < 0 ? 0 : maskY; // 计算结果赋给遮罩层 mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; // 5、按比例显示大图 // 5.1 放大比例 = 原图的宽度 / 大图的宽度 = 1 / 3 var rate = oneImgBox.offsetLeft / bigImg.offsetWidth; // 5.2 大图的移动距离 = 遮罩层的移动距离 * 放大比例 (注意大图的移动方向与遮罩层相反) bigImg.style.left = - maskX * 3 + 'px'; bigImg.style.top = - maskY * 3 + 'px'; }) </script> </html>
四、实现过程
1、HTML 页面结构
一个原图片的盒子【div元素】,里面放原图【img元素】和遮罩层【div元素】
一个放大后的图片盒子【div元素】,里面放大图【img元素】;
<body> <div class="one-img-box"> <img src="D:\test\girl.png" alt=""> <div class="mask"></div> </div> <div class="big-img-box"><img class="big-img" src="D:\test\girl.png" alt=""></div> </body>
2、CSS 元素样式
(1)两个盒子及图片样式
这里设置原图的宽高均为300px;大图的宽高是原图的三倍;
【 cursor: move; 】使得鼠标在移入图片变成“移动”样式;
【overflow: hidden;】使得图片超出盒子部分被隐藏(大图);
注意,大图盒子最初的的display的值应设为none,显隐性由鼠标移入或移出图片决定;
.one-img-box, .big-img-box { position: relative; width: 300px; height: 300px; box-shadow: 0 0 6px 1px #cacaca; border-radius: 10px; overflow: hidden; } .one-img-box { display: inline-block; top: 60px; left: 60px; cursor: move; } .one-img-box>img { width: 100%; height: 100%; } .big-img-box { display: inline-block; top: 60px; left: 100px; } .big-img-box>img { width: 300%; height: 300%; } .big-img { position: absolute; left: 0; top: 0; }
(2)遮罩层样式
遮罩层使用绝对定位,根据鼠标的移动位置,再更改其left和top值,使遮罩层跟随鼠标移动;
注意:遮罩层最初不显示,display的值也应设为none;
.mask { display: inline-block; position: absolute; left: 0; top: 0; width: 100px; height: 100px; background-color: yellowgreen; opacity: .4; }
注意:
原图的宽高均为300px;遮罩层的宽高均为100px;遮罩层与原图的宽高比例都是1 :3;
放大图的盒子和大图的比例需要一致(1 :3),所以大图的宽高应该均为900px;
这里的比例如果不一致,则会出现,遮罩层覆盖的内容,在大图中没有完全显示,或显示不全;当然可以自定义这个比例;
3、JavaScript动态控制
(1)获取页面元素
将页面中需要操作的元素都进行获取;
这里使用的是querySelector()方法来获取元素,是JavaScript中获取dom元素的方式之一;
<script> // 1、获取元素 // 获取原图的盒子 var oneImgBox = document.querySelector('.one-img-box'); // 获取遮罩层 var mask = document.querySelector('.mask'); // 获取大图盒子 var bigImgBox = document.querySelector('.big-img-box'); // 获取大图 var bigImg = document.querySelector('.big-img'); ...... </script>
(2)控制大图和遮罩层的显隐性
先设置大图盒子和遮罩层的display 为 none;
...... .big-img-box { /* display: inline-block; */ display: none; ...... } .mask { /* display: inline-block; */ display: none; ...... } ......
分析需求可知:
- 遮罩层和大图盒子的显示与隐藏是同时的,大图盒子显示则遮罩层显示,大图盒子隐藏则遮罩层隐藏;
- 当鼠标经过原图时,两者显示,需要给这个原图盒子注册鼠标经过事件,完成相应功能;
- 当鼠标移出原图时,两者隐藏,也需要给这个原图盒子注册鼠标移出事件,完成相应功能;
<script> ...... // 2、控制显示与隐藏 // 2.1 鼠标经过 oneImgBox,显示 mask遮挡层 和 bigImgBox大盒子; oneImgBox.addEventListener('mouseover', function () { mask.style.display = 'inline-block'; bigImgBox.style.display = 'inline-block'; }) // 2.2 鼠标移出 oneImgBox,隐藏 mask遮挡层 和 bigImgBox大盒子; oneImgBox.addEventListener('mouseout', function () { mask.style.display = 'none'; bigImgBox.style.display = 'none'; }) ...... </script>
(3)遮罩层跟随鼠标移动
分析需求可知:
- 遮罩层在盒子内的移动距离,实际就是鼠标的移动距离(遮罩层跟着鼠标移动),但注意这个是遮罩层左上角的位置;
- 遮罩层中心的移动距离,要在鼠标移动距离的基础上,减去遮罩层自身的宽度或高度;
- 鼠标的移动距离mouseX\mouseY为,鼠标在页面中的X坐标\Y坐标 - 图片盒子的左\上边距;
- 注意,这里鼠标一开始进入图片盒子就开始计算;
<script> ...... // 3、遮罩层跟随鼠标移动 oneImgBox.addEventListener('mousemove', function (e) { // 3.1 计算鼠标在盒子内的坐标 var mouseX = e.pageX - oneImgBox.offsetLeft; var mouseY = e.pageY - oneImgBox.offsetTop; // 3.2 计算遮罩层的移动位置 // 移动位置 = 鼠标的移动距离 - 遮罩层自己宽度\高度的一半(鼠标会在遮罩层中心位置,否则在左上角) var maskX = mouseX - mask.offsetWidth / 2; var maskY = mouseY - mask.offsetWidth / 2; // 计算结果赋给遮罩层; mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; ...... }) </script>
注意:
这里存在一个问题,就是当鼠标靠近图片边缘的时候,遮罩层会继续移动,被裁剪;
应该加以判断,控制遮罩层的移动范围,使得遮罩层不会被移出去;
(4)控制遮罩层移动范围
分析需求可知:
- 遮罩层的移动距离不能小于 0,也不能超过它的最大移动距离;
- 遮罩层最大移动宽度\高度 = 原图盒子的宽度\高度 - 遮罩层的宽度\高度;
- 如果移动距离 大于 最大移动距离,则取最大的移动距离;
- 如果移动距离 小于 0,则取0;
<script> ...... // 3、遮罩层跟随鼠标移动 oneImgBox.addEventListener('mousemove', function (e) { ...... // 4、控制遮罩层的移动范围 // 4.1 计算遮罩层最大移动宽度\高度 = 原图盒子的宽度\高度 - 遮罩层的宽度\高度 var maskMaxX = oneImgBox.offsetWidth - mask.offsetWidth; var maskMaxY = oneImgBox.offsetHeight - mask.offsetHeight // 如果移动距离 大于 最大移动距离,则取最大的移动距离 // 如果移动距离 小于 0,则取0; maskX = maskX > maskMaxX ? maskMaxX : maskX < 0 ? 0 : maskX; maskY = maskY > maskMaxY ? maskMaxY : maskY < 0 ? 0 : maskY; // 计算结果赋给遮罩层 mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; ...... }) </script>
(5)按比例移动放大图
分析需求可知:
- 放大比例 = 原图的宽度 / 大图的宽度;
- 大图的移动距离 = 遮罩层的移动距离 * 放大比例;
- 注意:大图的移动方向与遮罩层相反;
<script> ...... // 3、遮罩层跟随鼠标移动 oneImgBox.addEventListener('mousemove', function (e) { ...... // 5、按比例显示大图 // 5.1 放大比例 = 原图的宽度 / 大图的宽度 = 1 / 3 var rate = oneImgBox.offsetLeft / bigImg.offsetWidth; // 5.2 大图的移动距离 = 遮罩层的移动距离 * 放大比例 (注意大图的移动方向与遮罩层相反) bigImg.style.left = - maskX * 3 + 'px'; bigImg.style.top = - maskY * 3 + 'px'; }) </script>
=========================================================================
每天进步一点点~!
记录一下这个实用的前端"小轮子"~!