某东商品详情页图片放大镜功能

首先看看某东的效果:
在这里插入图片描述

这个案例可以分为三个功能模块:

  • 鼠标经过小图片的盒子,遮罩层和大图片盒子显示,离开隐藏遮罩层和大图片盒子。
  • 遮罩层跟随鼠标移动。
  • 移动遮罩层,大图片跟随移动。

要实现这个案例,我们需要用到下面几个知识点:

属性作用
element.offsetTop返回元素相对于带有定位父元素上边框的偏移量
element.offsetLeft返回元素相对于带有定位父元素左边框的偏移量
element.offsetWidth返回自身包括padding、边框、内容区的宽度,返回数值不带单位。
element.offsetHeight返回自身包括padding、边框、内容区的高度,返回数值不带单位。
event.pageX返回鼠标相对于整个文档的x坐标,返回数值不带单位
event.pageY返回鼠标相对于整个文档的y坐标,返回数值不带单位

首先先搭建页面布局:

<div class="box">
     <!-- 小盒子,存放一张小图片 -->
     <img src="./chuying.jpg">
     <!-- 遮罩层 -->
     <div class="mask"></div>
     <!-- 大盒子以及大图片 -->
     <div class="big">
         <img src="./chuying.jpg">
     </div>
 </div>

CSS:

 .box {
     position: relative;
     width: 300px;
     height: 300px;
     cursor: move;
 }
 
 .box img {
     width: 100%;
 }
 
 .box .mask {
     display: none;
     position: absolute;
     width: 150px;
     height: 150px;
     left: 0;
     top: 0;
     background-color: rgba(135, 206, 235, 0.5);
     border: 1px solid #cccccc;
 }
 
 .big {
     display: none;
     position: absolute;
     width: 600px;
     height: 600px;
     top: 0;
     left: 310px;
     border: 1px solid #ccc;
     overflow: hidden;
 }
 
 .big img {
     position: absolute;
     width: 800px;
     height: 800px;
     left: 0;
     top: 0;
 }

模块一:

鼠标经过小盒子,遮罩层和大图片盒子显示(display: block),这里有一个鼠标经过(mouseover)事件,鼠标离开(mouseout)小盒子,遮罩层和大图片盒子隐藏(display: none)。

这里只要给小盒子(.box)添加相应的鼠标事件,然后修改遮罩层和大图片盒子的display属性的值即可。

JS代码:

// 首先获取小盒子、遮罩层、大盒子三个元素
 var box = document.querySelector('.box');
 var mask = document.querySelector('.mask');
 var big = document.querySelector('.big');
 // 鼠标经过 box 就显示 mask遮罩层和 big 大盒子
 box.addEventListener('mouseover', function () {
     mask.style.display = 'block';
     big.style.display = 'block';
 })
 // 鼠标离开 box 就隐藏 mask遮罩层和 big 大盒子
 box.addEventListener('mouseout', function () {
     mask.style.display = 'none';
     big.style.display = 'none';
 })

模块一完成。

模块二:

遮罩层要跟随鼠标移动,首先要得到鼠标在小盒子里的位置,然后将鼠标在小盒子里的坐标分别给遮罩层的left和top。


 box.addEventListener('mousemove', function(e) {
     // 获得鼠标在小盒子内的位置
     var mouseX = e.pageX - this.offsetLeft;
     var mouseY = e.pageY - this.offsetTop;
     // 将鼠标的坐标赋值给遮罩层的left top
     mask.style.left = mouseX + 'px';
     mask.style.top = mouseY + 'px';
 })

此时就有一个问题,鼠标总是处于遮罩层的左上角:
在这里插入图片描述
想要鼠标在遮罩层的中间,修改鼠标的坐标不现实,我们可以修改遮罩层的left和top值,如果我们将left和top值分别减去遮罩层宽高的一半,就相当于将遮罩层往左和往上移动了自己的宽高的一半,此时鼠标的位置没变,那么遮罩层移动后的位置,鼠标刚好位于遮罩层的中心。


 box.addEventListener('mousemove', function(e) {
     // 获得鼠标在小盒子内的位置
     var mouseX = e.pageX - this.offsetLeft;
     var mouseY = e.pageY - this.offsetTop;
 // 将鼠标坐标减去遮罩层宽高的一半,得到新的遮罩层的偏移量
     var maskX = mouseX - mask.offsetWidth / 2;
     var maskY = mouseY - mask.offsetHeight / 2;
 // 设置遮罩层的偏移量
     mask.style.left = maskX + 'px';
     mask.style.top = maskY + 'px';
 })

此时,鼠标在遮罩层的中间了,同时遮罩层也跟随鼠标了,但是又有一个新的问题,遮罩层能移出小盒子:
在这里插入图片描述
要解决这个问题,就得设置遮罩层跟随鼠标移动时的边界,当鼠标的坐标减去遮罩层宽度的一半小于0时,就应该让遮罩层的left = 0;当鼠标的坐标减去遮罩层高度的一半小于0时,就应该让遮罩层的top = 0;那么遮罩层的最大偏移量就应该是小盒子的宽高减去遮罩层的宽高。


 box.addEventListener('mousemove', function(e) {
     // 获得鼠标在小盒子内的位置
     var mouseX = e.pageX - this.offsetLeft;
     var mouseY = e.pageY - this.offsetTop;
     // 将鼠标坐标减去遮罩层宽高的一半,得到新的遮罩层的偏移量
     var maskX = mouseX - mask.offsetWidth / 2;
     var maskY = mouseY - mask.offsetHeight / 2;
     // 遮罩层的最大的移动距离
     var maskXMax = this.offsetWidth - mask.offsetWidth;
     var maskYMax = this.offsetHeight - mask.offsetHeight;
 
     // 设置移动边界
     if (maskX < 0) {
         maskX = 0;
    } else if (maskX >= maskXMax) {
         maskX = maskXMax;
    }
     if (maskY < 0) {
         maskY = 0;
    } else if (maskY >= maskYMax) {
         maskY = maskYMax;
    }
 
     // 设置遮罩层的偏移量
     mask.style.left = maskX + 'px';
     mask.style.top = maskY + 'px';
 
 })

模块二完成。

模块三:

移动遮罩层,大图片跟随移动呈现放大的效果。要想实现这个效果,就要满足遮罩层的移动距离:遮罩层的最大移动距离 = 大图片的移动距离:大图片的最大移动距离这个条件。这个条件中,遮罩层的移动距离、遮罩层的最大移动距离、大图片的最大移动距离这三个参数,我们都是可求或已经求得了,那么大图片的移动距离 = 遮罩层的移动距离 * 大图片的最大移动距离 / 遮罩层的最大移动距离。

在模块二的基础上,添加下面代码片段。

 // 获取大图片
 var bigImg = document.querySelector('.big img');
 // 计算大图片的移动距离
 var bigImgX = maskX * (big.offsetWidth - bigImg.offsetWidth) / maskXMax;
 var bigImgY = maskY * (big.offsetHeight - bigImg.offsetHeight) / maskYMax;
 // 设置大图片的偏移量
 bigImg.style.left = bigImgX + 'px';
 bigImg.style.top = bigImgY + 'px';    

模块三完成。

案例的完整的JS代码:


 // 首先获取小盒子、遮罩层、大盒子三个元素
 var box = document.querySelector('.box');
 var mask = document.querySelector('.mask');
 var big = document.querySelector('.big');
 // 鼠标经过 box 就显示 mask遮罩层和 big 大盒子
 box.addEventListener('mouseover', function () {
     mask.style.display = 'block';
     big.style.display = 'block';
 })
 // 鼠标离开 box 就隐藏 mask遮罩层和 big 大盒子
 box.addEventListener('mouseout', function () {
     mask.style.display = 'none';
     big.style.display = 'none';
 })
 
 box.addEventListener('mousemove', function(e) {
     // 获得鼠标在小盒子内的位置
     var mouseX = e.pageX - this.offsetLeft;
     var mouseY = e.pageY - this.offsetTop;
     // 将鼠标坐标减去遮罩层宽高的一半,得到新的遮罩层的偏移量
     var maskX = mouseX - mask.offsetWidth / 2;
     var maskY = mouseY - mask.offsetHeight / 2;
     // 遮罩层的最大的移动距离
     var maskXMax = this.offsetWidth - mask.offsetWidth;
     var maskYMax = this.offsetHeight - mask.offsetHeight;
 
     // 设置移动边界
     if (maskX < 0) {
         maskX = 0;
    } else if (maskX >= maskXMax) {
         maskX = maskXMax;
    }
     if (maskY < 0) {
         maskY = 0;
    } else if (maskY >= maskYMax) {
         maskY = maskYMax;
    }
 
     // 设置遮罩层的偏移量
     mask.style.left = maskX + 'px';
     mask.style.top = maskY + 'px';
 
     // 获取大图片
     var bigImg = document.querySelector('.big img');
     // 计算大图片的移动距离
     var bigImgX = maskX * (big.offsetWidth - bigImg.offsetWidth) / maskXMax;
     var bigImgY = maskY * (big.offsetHeight - bigImg.offsetHeight) / maskYMax;
     // 设置大图片的偏移量
     bigImg.style.left = bigImgX + 'px';
     bigImg.style.top = bigImgY + 'px';          
 })

最后来看下最终的效果,对比一下某东的效果是否一致。
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就是不掉头发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值