1 案例描述

在很多网页中,我们都能看到一个类似于放大镜的效果,一般显示为有一个小的图,旁边有一个大图,当鼠标在小图上来回移动时,大图也会在相应的位置上来回移动,这样的效果一般在购物网站、制图网站上很常见,方便用户查看各种细节。

案例设计分析图:
在这里插入图片描述
效果图如下:
在这里插入图片描述
该效果主要是由2个div构成,一个放置小的图片,另一个放置大的,当鼠标在小效果图上来回移动时,会按照比例显示相应部分的大效果图。

2 编写HTML代码

在html部分中,要写入两个div,一个放置小图和遮罩层,另一个放置大图,代码如下:

    <!-- 图片预览区域 -->
    <div class="preview">
        <!-- 小图 -->
        <img src="./phone.png">
        <!-- 遮罩层 -->
        <div class="mask"></div>
    </div>
    <!-- 图片放大区域 -->
    <div class="big_show">
        <!-- 大图 -->
        <img src="./bigphone.png">
    </div>

在这里插入图片描述

3 编写CSS代码

首先为图片预览区域设置样式,为其设置宽和高,设置一个边框,方便对边界看得更加清楚,最后设置一个相对定位,为了让里面的遮罩层在设置绝对定位后位置相对于该区域定位,代码如下:

    /* 为图片预览区域设置样式 */
    .preview {
        width: 200px;
        height: 200px;
        border: 1px solid red;
        position: relative;
    }

在这里插入图片描述
从效果图可以看出,小图片太大,无法放入预览区中,因此为小图片设置一个高和宽,代码如下:

    /* 为小图片设置样式 */
    .preview img {
        width: 200px;
        height: 200px;
    }

在这里插入图片描述
让两个图片显示在一行上面,因此为<body></body>设置弹性盒子样式,代码如下:

    /* 让两个元素显示在一行 */
    body {
        display: flex;
    }

在这里插入图片描述
为图片显示区域设置样式,给其设置宽和高(要比大图片小)、边框、绝对定位(方便定位里面的img元素),为其设置盒子之外的部分不可见,最后将其隐藏,代码如下:

    /* 图片显示区域 */
    .big_show {
        width: 400px;
        height: 400px;
        border: 1px solid blue;
        /* 盒子外面的部分不可见 */
        overflow: hidden;
        /* 绝对定位,距离页面左边300像素 */
        position: absolute;
        left: 300px;
        /* 将其隐藏 */
        display: none;
    }

注:下面的图片是没有将其隐藏时的效果,也就是上面的代码中,不写入display: none;时的效果。
在这里插入图片描述
为大图片设置样式,将大图片的宽和高设置好,方便JavaScript部分按照比例显示图片,然后为图片设置绝对定位,方便JavaScript部分对图片进行定位,代码如下:

    /* 为大图片设置样式 */
    .big_show img {
        position: absolute;
        width: 800px;
        height: 800px;
    }

注:下面的图片是没有将其隐藏时的效果,也就是图片显示区域(big_show)的代码中,不写入display: none;时的效果。
在这里插入图片描述
为遮罩层设置样式,给它设置宽高、绝对定位、背景颜色,以及先将其隐藏起来,代码如下:

    /* 为遮罩层设置样式 */
    .mask {
        width: 100px;
        height: 100px;
        position: absolute;
        left: 0;
        top: 0;
        /* rgba最后一个参数为透明度 */
        background-color: rgba(255, 0, 0, 0.2);
        /* 先将其隐藏起来 */
        display: none;
    }

注:下面的效果图为遮罩层样式不加display: none;时的效果
在这里插入图片描述
到这里CSS样式就编写完成了,当前页面上的效果如下:在这里插入图片描述

4 编写JavaScript代码

首先获取页面中需要使用到的元素,分别是:图片预览区、遮罩层、图片显示区以及大图片,代码如下:

        //1、获取页面中的元素
        let preview = document.querySelector(".preview");//获取预览区
        let mask = document.querySelector(".mask");//获取遮罩层
        let big_show = document.querySelector(".big_show");//获取显示区
        let big_img = big_show.querySelector("img");//获取大图片

然后为预览区写入鼠标移动事件,当鼠标移动到预览区中时,显示遮罩层和图片显示区,当鼠标在预览区四处移动时,图片显示区域也会相应地显示出预览区遮罩层下面的部分,具体的解释在代码的注释中。

        preview.onmousemove = function (e) {//当鼠标在预览区移动时
            mask.style.display = "block";//显示遮罩层
            big_show.style.display = "block";//显示图片显示区
            //鼠标在盒子中的横坐标=鼠标在页面中的横坐标-预览区在页面中的横坐标
            //然后鼠标在盒子中的横坐标需要赋值给遮罩层在预览区中的横坐标,这时鼠标的位置正好对应遮罩层最左边
            //为了让鼠标显示在遮罩层的中心,遮罩层在预览区中的横坐标需要再减去1/2遮罩层的宽度
            //遮罩层在预览区的横坐标=鼠标在页面中的坐标-预览区对页面坐标的偏移量-
            let x = e.pageX - preview.offsetLeft - mask.offsetWidth / 2;
            //纵坐标与横坐标原理相同
            let y = e.pageY - preview.offsetTop - mask.offsetHeight / 2;
            //获取遮罩层最大的移动距离,最大移动距离不超过图片预览区域
            //(这是一个固定的数字)水平最大移动距离=预览区的宽度-遮罩层的宽度
            let x_max = preview.offsetWidth - mask.offsetWidth;
            //(这时一个固定的数字)垂直最大移动距离=预览区的高度-遮罩层的高度
            let y_max = preview.offsetHeight - mask.offsetHeight;
            //根据最大移动距离限制遮罩层水平方向的移动范围
            if (x < 0) {//如果遮罩层在左侧要移出预览区
                x = 0;//让遮罩层的横坐标为0,无法出去
            } else if (x > x_max) {//如果遮罩层最右侧要移出预览区
                x = x_max;//遮罩层的横坐标恒为最大移动距离
            }
            //根据最大移动距离限制遮罩层垂直方向的移动范围
            if (y < 0) {//如果遮罩层在上方要移出预览区
                y = 0;//让遮罩层的纵坐标恒为0,无法移出
            } else if (y > y_max) {//如果遮罩层在下方要移出预览区
                y = y_max;//让遮罩层的纵坐标恒为最大值
            }
            //将计算好的遮罩层的坐标x和y赋值给遮罩层,让其跟随鼠标进行移动
            mask.style.left = x + "px";
            mask.style.top = y + "px";
            //遮罩层的坐标比整个预览区的宽度,得到两个比值,该比值是移动距离的比值
            let x_pro = x / preview.offsetWidth;
            let y_pro = y / preview.offsetHeight;
            //大图片的移动距离=移动距离的比值×大图片的宽高
            let x_big = x_pro * big_img.offsetWidth;
            let y_big = y_pro * big_img.offsetHeight;
            //由于图片显示区域是固定不变的,是大图片的位置在改变
            //当遮罩层在预览区向右移动一段距离,那么大图片在显示区必须向左移动一定比例的距离
            //这样才能显示在显示区域(big_show)中,因此为大图片的移动距离赋值时
            //需要将大图片的移动距离变成负值
            big_img.style.left = -x_big + "px";
            big_img.style.top = -y_big + "px";
        }

在这部分中,首先获得遮罩层mask在图片预览区preview中的横坐标x和纵坐标y,这部分比较抽象难以理解,因此以获取遮罩层mask在图片预览区preview的横坐标x为例,设计出以下示意图:
在这里插入图片描述


为预览区写鼠标移出事件,当鼠标移出预览区时,遮罩层隐藏,显示区域隐藏,代码如下:

        //给预览区注册鼠标移开事件
        preview.onmouseleave = function () {
            mask.style.display = "none";//遮罩层隐藏
            big_show.style.display = "none";//图片显示区域隐藏
        }

5 总代码

<!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>
</head>
<style>
    /* 让两个元素显示在一行 */
    body {
        display: flex;
    }

    /* 为图片预览区域设置样式 */
    .preview {
        width: 200px;
        height: 200px;
        border: 1px solid red;
        position: relative;
    }

    /* 为小图片设置样式 */
    .preview img {
        width: 200px;
        height: 200px;
    }

    /* 图片显示区域 */
    .big_show {
        width: 400px;
        height: 400px;
        border: 1px solid blue;
        /* 盒子外面的部分不可见 */
        overflow: hidden;
        /* 绝对定位,距离页面左边300像素 */
        position: absolute;
        left: 300px;
        /* 将其隐藏 */
        display: none;
    }

    /* 为大图片设置样式 */
    .big_show img {
        position: absolute;
        width: 800px;
        height: 800px;
    }

    /* 为遮罩层设置样式 */
    .mask {
        width: 100px;
        height: 100px;
        position: absolute;
        left: 0;
        top: 0;
        /* rgba最后一个参数为透明度 */
        background-color: rgba(255, 0, 0, 0.2);
        /* 先将其隐藏起来 */
        display: none;
    }
</style>

<body>
    <!-- 图片预览区域 -->
    <div class="preview">
        <!-- 小图 -->
        <img src="./phone.png">
        <!-- 遮罩层 -->
        <div class="mask"></div>
    </div>
    <!-- 图片放大区域 -->
    <div class="big_show">
        <!-- 大图 -->
        <img src="./bigphone.png">
    </div>
    <script>
        //1、获取页面中的元素
        let preview = document.querySelector(".preview");//获取预览区
        let mask = document.querySelector(".mask");//获取遮罩层
        let big_show = document.querySelector(".big_show");//获取显示区
        let big_img = big_show.querySelector("img");//获取大图片
        preview.onmousemove = function (e) {//当鼠标在预览区移动时
            mask.style.display = "block";//显示遮罩层
            big_show.style.display = "block";//显示图片显示区
            //鼠标在盒子中的横坐标=鼠标在页面中的横坐标-预览区在页面中的横坐标
            //然后鼠标在盒子中的横坐标需要赋值给遮罩层在预览区中的横坐标,这时鼠标的位置正好对应遮罩层最左边
            //为了让鼠标显示在遮罩层的中心,遮罩层在预览区中的横坐标需要再减去1/2遮罩层的宽度
            //遮罩层在预览区的横坐标=鼠标在页面中的坐标-预览区对页面坐标的偏移量-
            let x = e.pageX - preview.offsetLeft - mask.offsetWidth / 2;
            //纵坐标与横坐标原理相同
            let y = e.pageY - preview.offsetTop - mask.offsetHeight / 2;
            //获取遮罩层最大的移动距离,最大移动距离不超过图片预览区域
            //(这是一个固定的数字)水平最大移动距离=预览区的宽度-遮罩层的宽度
            let x_max = preview.offsetWidth - mask.offsetWidth;
            //(这时一个固定的数字)垂直最大移动距离=预览区的高度-遮罩层的高度
            let y_max = preview.offsetHeight - mask.offsetHeight;
            //根据最大移动距离限制遮罩层水平方向的移动范围
            if (x < 0) {//如果遮罩层在左侧要移出预览区
                x = 0;//让遮罩层的横坐标为0,无法出去
            } else if (x > x_max) {//如果遮罩层最右侧要移出预览区
                x = x_max;//遮罩层的横坐标恒为最大移动距离
            }
            //根据最大移动距离限制遮罩层垂直方向的移动范围
            if (y < 0) {//如果遮罩层在上方要移出预览区
                y = 0;//让遮罩层的纵坐标恒为0,无法移出
            } else if (y > y_max) {//如果遮罩层在下方要移出预览区
                y = y_max;//让遮罩层的纵坐标恒为最大值
            }
            //将计算好的遮罩层的坐标x和y赋值给遮罩层,让其跟随鼠标进行移动
            mask.style.left = x + "px";
            mask.style.top = y + "px";
            //遮罩层的坐标比整个预览区的宽度,得到两个比值,该比值是移动距离的比值
            let x_pro = x / preview.offsetWidth;
            let y_pro = y / preview.offsetHeight;
            //大图片的移动距离=移动距离的比值×大图片的宽高
            let x_big = x_pro * big_img.offsetWidth;
            let y_big = y_pro * big_img.offsetHeight;
            //由于图片显示区域是固定不变的,是大图片的位置在改变
            //当遮罩层在预览区向右移动一段距离,那么大图片在显示区必须向左移动一定比例的距离
            //这样才能显示在显示区域(big_show)中,因此为大图片的移动距离赋值时
            //需要将大图片的移动距离变成负值
            big_img.style.left = -x_big + "px";
            big_img.style.top = -y_big + "px";
        }
        //给预览区注册鼠标移开事件
        preview.onmouseleave = function () {
            mask.style.display = "none";//遮罩层隐藏
            big_show.style.display = "none";//图片显示区域隐藏
        }
    </script>
</body>

</html>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐