js 实现放大镜

1,378 阅读2分钟

前言

图片放大镜特效大家应该都司空见惯了。当你逛淘宝天猫,浏览京东时。将鼠标移动到缩略图上,就会出现一块遮罩,且旁边还会显示一张高清图,显示的内容就是遮罩区域的图片的放大版。但有的小伙伴可能还不太明白其中的原理,今天就带着大家一起研究一下。

原理解析

  1. 准备两张图片(当然一张也可以,不过分辨率要高一点),一张缩略图,一张高清图。
  2. 当鼠标移动到缩略图上时,显示遮罩和高清图。悬浮显示可以使用css hover伪类控制,或者js绑定mouseover,mouseout。
  3. 绑定mousemove事件,鼠标移动时更新遮罩和高清图的位置。

遮罩区域如何实现?

image.png

其实很简单,就是利用css background属性设置背景图片,然后不断的重复图片形成的效果。只不过这张图片很小。遮罩区域放大后是这个样子的。

image.png

这样做的好处是你可以通过css来控制遮罩区域的大小,比较灵活。

边界判断

由于鼠标的位置是显示在遮罩区域的中心的。所以不能以缩略图的上下左右为边界来判断,鼠标移动的区域如下图红框所示:

image.png

边界判断思路:

  1. 使用Element.getBoundingClientRect()方法获取绿框相对于屏幕的位置
  2. 获取遮罩区域的宽高
  • 红框鼠标移动左边界:绿框距离屏幕左边的距离 + 遮罩区域宽度的一半
  • 红框鼠标移动右边界:绿框距离屏幕左边的距离 + 绿框宽度 - 遮罩区域宽度的一半
  • 红框鼠标移动上边界:绿框距离屏幕顶部的距离 + 遮罩区域高度的一半
  • 红框鼠标移动下边界:绿框距离屏幕顶部的距离 + 绿框高度 - 遮罩区域高度的一半

完整代码

HTML:

<div class="container">
    <div class="small">
        <img src="../images/liya.jpg" alt="">
        <div class="mask"></div>
    </div>
    <div class="big">
        <img src="../images/liya.jpg" alt="">
    </div>
</div>

CSS:

* {
    margin: 0;
    padding: 0;
}
.container {
    display: flex;
    align-items: flex-start;
    padding: 15px;
}
.small {
    position: relative;
    margin-right: 15px;
    cursor: move;
}
.small img {
    display: block;
    width: 400px;
}
.big {
    visibility: hidden;
    width: 400px;
    height: 400px;
    overflow: hidden;
}
.big img {
    display: block;
    width: 800px;
}
.mask {
    visibility: hidden;
    position: absolute;
    top: 0;
    left: 0;
    width: 200px;
    height: 200px;
    background-image: url('../images/point.png');
    pointer-events: none;
}
.small:hover .mask {
    visibility: visible;
}
.small:hover ~ .big {
    visibility: visible;
}

JS:

// 小图容器
const small = {
    element: document.querySelector('.small'),
    width: 400,
    height: 320
};
const smallRect = small.element.getBoundingClientRect();
// 放大镜遮罩
const mask = {
    element: document.querySelector('.mask'),
    width: 200,
    height: 200,
    halfWidth: 100,
    halfHeight: 100
};
// 大图容器
const big = document.querySelector('.big');
// 大图
const bigImg = document.querySelector('.big img');
// 全局变量
let x, y;
const bounding = {
    left: 0,
    right: small.width - mask.width,
    top: 0,
    bottom: small.height - mask.height
}
// 绑定mousemove
small.element.addEventListener('mousemove', function (e) {
    x = e.clientX - smallRect.left - mask.halfWidth;
    y = e.clientY - smallRect.top - mask.halfHeight;
    // 边界判断
    if (x < bounding.left) {
        x = bounding.left;
    } else if (x > bounding.right) {
        x = bounding.right;
    }
    if (y < bounding.top) {
        y = bounding.top;
    } else if (y > bounding.bottom) {
        y = bounding.bottom;
    }
    mask.element.style.transform = 'translate3d(' + x + 'px ,' + y + 'px, 0)';
    bigImg.style.transform = 'translate3d(' + (x * -2) + 'px ,' + (y * -2) + 'px, 0)';
});

Demo:jsdemo.codeman.top/html/magnif…