前言
图片放大镜特效大家应该都司空见惯了。当你逛淘宝天猫,浏览京东时。将鼠标移动到缩略图上,就会出现一块遮罩,且旁边还会显示一张高清图,显示的内容就是遮罩区域的图片的放大版。但有的小伙伴可能还不太明白其中的原理,今天就带着大家一起研究一下。
原理解析
- 准备两张图片(当然一张也可以,不过分辨率要高一点),一张缩略图,一张高清图。
- 当鼠标移动到缩略图上时,显示遮罩和高清图。悬浮显示可以使用css hover伪类控制,或者js绑定mouseover,mouseout。
- 绑定mousemove事件,鼠标移动时更新遮罩和高清图的位置。
遮罩区域如何实现?
其实很简单,就是利用css background属性设置背景图片,然后不断的重复图片形成的效果。只不过这张图片很小。遮罩区域放大后是这个样子的。
这样做的好处是你可以通过css来控制遮罩区域的大小,比较灵活。
边界判断
由于鼠标的位置是显示在遮罩区域的中心的。所以不能以缩略图的上下左右为边界来判断,鼠标移动的区域如下图红框所示:
边界判断思路:
- 使用Element.getBoundingClientRect()方法获取绿框相对于屏幕的位置
- 获取遮罩区域的宽高
- 红框鼠标移动左边界:绿框距离屏幕左边的距离 + 遮罩区域宽度的一半
- 红框鼠标移动右边界:绿框距离屏幕左边的距离 + 绿框宽度 - 遮罩区域宽度的一半
- 红框鼠标移动上边界:绿框距离屏幕顶部的距离 + 遮罩区域高度的一半
- 红框鼠标移动下边界:绿框距离屏幕顶部的距离 + 绿框高度 - 遮罩区域高度的一半
完整代码
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)';
});