JavaScript实现仿京东放大镜特效教程

作者:半夏时间:2026-10-24 18:58:38浏览:195

本文详细解析如何使用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 放大镜特效的资料请关注本站其它相关文章!

作者最新文章