Javascript 放大镜特效 Javascript实例项目放大镜特效的实现流程
X-77 人气:0前言
本票博客主要是放大镜案例,里面涉及到的知识点会提出来,可放心食用~后有源代码。
案例:仿京东放大镜效果
效果见下图:
功能要求:
- 当鼠标移动到小图片上时,遮罩层出现,同时旁边大图片也出现,鼠标移出,遮罩层消失,大图片也消失。
- 遮罩层只能在小盒内子移动,不能超出。
- 遮罩层在小盒子内移动,大图片显示对应的板块。
案例分析:
- 元素的隐层和显示
- 遮罩层的移动范围用offset计算
- 计算出大盒子内移动的距离
案例代码:
首先咱们应该将结构搭建好,结构大致为:
先将各个盒子的样式全部书写完毕后,把蓝色遮罩层盒子和右边的装红色大图片的盒子隐藏起来,注意,紫色的盒子是相对定位,所有盒子的定位都是根据紫色盒子进行定位的。
代码如下:
<div class="box"> <img src="./image/pic1.jpg" alt="" class="box_pic"> <div class="mask"></div> <div class="big"> <img src="./image/bigimg.jpg" alt="" class="bigImg"> </div> </div>
搭建好后,我们给这个box盒子添加鼠标移动事件,当鼠标移动到box上时,mask盒子和big盒子出现,鼠标移出后,mask盒子和big盒子消失。
代码如下:
var pic = document.querySelector('.box'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); //出现 消失 pic.addEventListener('mouseenter', function () { mask.style.display = 'block'; big.style.display = 'block'; }) pic.addEventListener('mouseleave', function () { mask.style.display = 'none'; big.style.display = 'none'; })
接着我们就需要计算一下遮罩层可以移动的距离。
由上图可见,因为我们要求遮罩层不能超出小盒子的范围,所以遮罩层能在小盒子内移动的距离就只有小盒子的宽度减去遮罩层盒子的宽度,此时我们使用offset中的属性。
offset系列
使用 offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等
offset系列属性:
注意:offset系列只有offsetTop和offsetLeft!!!且返回的值是不带单位的。
对比:offset和style属性
offset
styleoffset 可以得到任意样式表中的样式值style 只能得到行内样式表中的样式值
offset 系列获得的数值是没有单位的
style.width 获得的是带有单位的字符串 offsetWidth 包含padding+border+widthstyle.width 获得不包含padding和border 的值offsetWidth 等属性是只读属性,只能获取不能赋值style.width 是可读写属性,可以获取也可以赋值总结:适合获取元素大小位置总结:适合给元素更改值
那么接下来我们先使用e.pageX和e.pageY获取到鼠标当前的坐标,得到之后用e.pageX-box.offsetLeft得到的就是盒子里面的鼠标的位置了,话不多说,看图解!
黑线-红线得到的距离就是当前鼠标在盒子内的位置。另外 由于遮罩层是一个盒子,鼠标定位是紧贴着盒子的左上角的,我们需要将盒子往上移动50%,往右移动50%,让鼠标与盒子的中心点对齐。最后我们得到鼠标的位置,并且判断当前是否处于盒子内部,即判断这个移动的位置是否处于大于0且小于最大移动距离之间。
代码如下:
pic.addEventListener('mousemove', function (e) { var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // mask移动距离 var maskX = x - mask.offsetWidth / 2; var maskY = y - mask.offsetHeight / 2; var maskMax = pic.offsetWidth - mask.offsetWidth; // 判断是否在盒子内部 if (maskX <= 0) { maskX = 0; } else if (maskX >= maskMax) { maskX = maskMax; } if (maskY <= 0) { maskY = 0; } else if (maskY >= maskMax) { maskY = maskMax; } mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; }
现在我们可以看到遮罩层可以在盒子内部移动,并且不会超出盒子的范围,那么本项目就到了最后一步,即让旁边的大盒子里的图片能够显示出对应的区块。
因为两张图片的比例相同,我们可以按照下图公式进行计算:
即:大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
代入公式,我们就可以得到大图片的移动距离。注意,当我们鼠标从左往右滑时,大图片应该是从右往左移,所以应该是负值。
代码如下:
// 大图片的最大移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离 var bigImg = document.querySelector('.bigImg'); bigMax = bigImg.offsetWidth - big.offsetWidth; var bigX = maskX * bigMax / maskMax; var bigY = maskY * bigMax / maskMax; bigImg.style.left = -bigX + 'px'; bigImg.style.top = -bigY + 'px';
至此,我们放大镜的项目就完成啦,一步一步解析下来还是很简单的!主要是使用了offset系列属性,那么介绍了offset系列属性,不介绍一下他的另外两个小伙伴怎么能行?补充介绍一下client系列和scroll系列。
完整代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .box { position: relative; margin: 30px; width: 300px; height: 300px; /* pointer-events: none; */ /* cursor: alias; */ /* cursor: default; */ } .box_pic { width: 300px; height: 300px; border: 1px solid #ccc; } .mask { display: none; position: absolute; top: 0; left: 0; width: 200px; height: 200px; background-color: rgb(54, 240, 240); opacity: 0.5; cursor: all-scroll; z-index: 9; } .big { display: none; position: absolute; top: 0; left: 320px; width: 500px; height: 500px; overflow: hidden; border: 1px solid #ccc; } .big img { position: absolute; width: 800px; height: 800px; } </style> </head> <body> <div class="box"> <img src="./image/pic1.jpg" alt="" class="box_pic"> <div class="mask"></div> <div class="big"> <img src="./image/bigimg.jpg" alt="" class="bigImg"> </div> </div> </div> <script> var pic = document.querySelector('.box'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); //出现 消失 pic.addEventListener('mouseenter', function () { mask.style.display = 'block'; big.style.display = 'block'; }) pic.addEventListener('mouseleave', function () { mask.style.display = 'none'; big.style.display = 'none'; }) // 移动 //获取鼠标位置 pic.addEventListener('mousemove', function (e) { var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // mask移动距离 var maskX = x - mask.offsetWidth / 2; var maskY = y - mask.offsetHeight / 2; var maskMax = pic.offsetWidth - mask.offsetWidth; // 判断是否在盒子内部 if (maskX <= 0) { maskX = 0; } else if (maskX >= maskMax) { maskX = maskMax; } if (maskY <= 0) { maskY = 0; } else if (maskY >= maskMax) { maskY = maskMax; } mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; // 大图片的最大移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离 var bigImg = document.querySelector('.bigImg'); bigMax = bigImg.offsetWidth - big.offsetWidth; var bigX = maskX * bigMax / maskMax; var bigY = maskY * bigMax / maskMax; bigImg.style.left = -bigX + 'px'; bigImg.style.top = -bigY + 'px'; }) </script> </body> </html>
client系列
使用 client 系列的相关属性来获取元素可视区的相关信息。
client系列属性:
注意:client包含padding值,返回值也不带单位。
scroll系列
使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
scroll系列属性:
三大系列总结
三大系列的内容包含:
主要用法如下:
offset系列 经常用于获得元素位置 offsetLeft offsetTopclient经常用于获取元素大小 clientWidth clientHeightscroll 经常用于获取滚动距离 scrollTop scrollLeft 注意页面滚动的距离通过 window.pageXOffset 获得
看完这篇博客,是不是把放大镜案例直接拿下!本案例不算难,主要是通过这个案例复习BOM对象中的offset、client和scroll。我们还可以通过这些知识点完成模态框的制作、消灭星星案例哦~
加载全部内容