JavaScript实现仿京东放大镜特效教程
本文详细解析如何使用JavaScript实现仿京东的放大镜特效。通过监听鼠标事件控制遮罩层与大图的显隐,利用offset系列属性计算移动范围,结合比例公式同步大图位置。文中还对比了offset、client与scroll系列属性的区别,帮助开发者掌握BOM对象在交互开发中的应用。
前言
本文主要介绍一个放大镜案例,其中涉及的知识点会逐一列出,读者可放心阅读,文末附有完整源代码。
案例:仿京东放大镜效果
效果见下图:

功能要求:
- 当鼠标移入小图片区域时,遮罩层出现,同时右侧的大图片区域也显示;鼠标移出时,遮罩层和大图片均消失。
- 遮罩层仅能在小盒子内部移动,不可超出边界。
- 遮罩层在小盒子内移动时,大图片需显示对应的区域。
案例分析:
- 涉及元素的隐藏与显示逻辑。
- 利用offset计算遮罩层的移动范围。
- 计算大盒子内图片的移动距离。
案例代码:
首先搭建HTML结构,大致结构如下:

编写各盒子的样式,初始时将蓝色遮罩层盒子和右侧装红色大图片的盒子隐藏。注意,紫色盒子设置为相对定位,其他所有盒子的定位均基于该紫色盒子进行。
代码如下:
<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
offset可获取任意样式表中的样式值,而style仅能获取行内样式表中的样式值。
offset系列获得的数值没有单位。
style.width获得带有单位的字符串,offsetWidth包含padding、border和width;style.width获得不包含padding和border的值。offsetWidth等属性为只读,仅能获取不能赋值;style.width为可读写,既可获取也可赋值。总结:offset系列适合获取元素大小和位置,style适合给元素更改值。
接下来使用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、offsetTop);client常用于获取元素大小(clientWidth、clientHeight);scroll常用于获取滚动距离(scrollTop、scrollLeft)。注意页面滚动的距离通过window.pageXOffset获得。
看完本篇博客,是否觉得拿下放大镜案例易如反掌?本案例难度适中,主要借此复习BOM对象中的offset、client和scroll系列。此外,还可利用这些知识点完成模态框制作、消灭星星等案例。
以上就是Javascript实例项目放大镜特效的实现流程的详细内容,更多关于Javascript 放大镜特效的资料请关注本站其它相关文章!
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
