js实现放大镜,先来看效果
鼠标移动到左侧区域,右侧区域放大图片对应的位置
首先来看html部分,一共由3个div组成
html
<!-- 图片盒子 -->
<div class="box">
<!-- 放大镜 -->
<div class="area"></div>
</div>
<!-- 放大后的区域 -->
<div class="zoom-content"></div>
下面来编写一下css
css
.box{
display: inline-block;
position: relative;
width:400px;
height:400px;
border:1px solid red;
background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
background-size: 100% 100%;
vertical-align: top;
}
.area{
position: absolute;
width:200px;
height:200px;
background-color: rgba(0, 0, 255,.5);
cursor: move;
}
.zoom-content{
display: inline-block;
width:500px;
height:500px;
border:1px solid red;
background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
background-repeat: no-repeat;
}
编写完成后如图 下面开始js逻辑部分
1.我们首先开始实现第一个功能,鼠标移入框内后,让蓝色的盒子(放大镜)跟着鼠标移动
js
// 先获取DOM元素
let area = document.querySelector('.area'); // 放大镜
let box = document.querySelector('.box'); // 图片盒子
let zoom = document.querySelector('.zoom-content'); //右侧放大区域
// 放大镜蓝色背景盒子尺寸
let areaWidth = area.clientWidth;
let areaHeight = area.clientHeight;
// 鼠标移入后的事件
const enter = (event) => {
// 设置放大镜的位置
setAreaPosition(event);
box.addEventListener("mousemove",move);
box.addEventListener("mouseleave",leave);
}
// 鼠标移动事件
const move = (event) => {
setAreaPosition(event);
}
//鼠标移出后 取消绑定一下
const leave = () => {
box.removeEventListener("mousemove",move);
box.removeEventListener("mouseleave",leave);
}
// 设置放大镜的位置
const setAreaPosition = (event) => {
// 让放大镜垂直居中显示在鼠标移动后的位置 需减去自身方向的一半
let x = event.x - areaWidth / 2;
let y = event.y - areaHeight / 2;
area.style.left = x+"px";
area.style.top = y+"px";
}
box.addEventListener("mouseenter",enter);
这样就能让放大镜跟随鼠标移动了,但是有点瑕疵,需要让放大镜一直保持在盒子里面,需要判断一下距离边界情况
js
// 图片盒子大小尺寸
let boxWidth = box.clientWidth;
let boxHeight = box.clientHeight;
// 放大镜X轴极限距离
let maxX = boxWidth - areaWidth;
// 放大镜Y轴极限距离
let maxY = boxHeight - areaHeight;
maxX,maxY就是边界的距离,我们需要在setAreaPosition函数中,对x轴,y轴的大小做一下限制
js
const setAreaPosition = (event) => {
// 让放大镜垂直居中显示在鼠标移动后的位置 需减去自身方向的一半
let x = event.x - areaWidth / 2;
let y = event.y - areaHeight / 2;
// x的值不能大于maxX,同时不能小于0,y的判断同理
x = Math.min(maxX,Math.max(0,x));
// y的值不能大于maxY,同时不能小于0
y = Math.min(maxY,Math.max(0,y));
area.style.left = x+"px";
area.style.top = y+"px";
}
通过Math.min方法和Math.max方法就能对x,y极限值做限制了
下面我们来设置一下右侧放大区域,目前来看它并没有放大,而是保持了图片本来的大小,下面是js部分
js
// 先获取一下缩放的倍率,也就是放大镜和图片盒子做对比
// 缩放倍率
let xScale = boxWidth / areaWidth;
let yScale = boxHeight / areaHeight;
// 知道了倍率后,我们对放大区域的图片大小做一下设置
// 因为使用的是背景图片所以需设置一下backgroundSize属性
zoom.style.backgroundSize=`${xScale * 100}% ${yScale * 100}%`;
这一部分呢可以理解为把右侧的放大区域(.zoom-content)看作是放大镜(.area);
下面只差最后一部分了,移动鼠标,让右侧放大区域改变,只需要改变(.zoom-content)的backgroundPosition即可
那的backgroundPosition的值怎么计算呢?
绿色背景假设为图片,左侧的蓝色是放大镜,右侧的蓝色是放大后的区域,这样就一目了然了,先算出放大镜距离图片盒子的多少比例,然后在拿这个比例去算出占放大后的背景多少像素就可以了
js
// 缩放后的图片尺寸
let bgWidth = zoom.clientWidth * xScale;
let bgHeight = zoom.clientHeight * yScale;
setAreaPosition函数修改一下
js
// 设置放大镜的位置
const setAreaPosition = (event) => {
let x = event.x - areaWidth / 2;
let y = event.y - areaHeight / 2;
// x的值不能大于maxX,同时不能小于0,y的判断同理
x = Math.min(maxX,Math.max(0,x));
// y的值不能大于maxY,同时不能小于0
y = Math.min(maxY,Math.max(0,y));
area.style.left = x+"px";
area.style.top = y+"px";
// 计算背景距离,为什么为负数,负数图片为往右走,正数为左走
// x / boxWidth 放大镜距离左侧的比例,根据这个比例 * 相应的图片宽度,就知道图片要走到哪里了
zoom.style.backgroundPosition = `${-(x / boxWidth * bgWidth)}px ${-(y / boxHeight * bgHeight)}px`;
}
后续可以在移入和移出时改变(.area)放大镜的visibility就行
js
// enter 移入
area.style.visibility = 'visible';
// leave 移出
area.style.visibility = 'hidden';
完整代码如下
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
display: inline-block;
position: relative;
width:400px;
height:400px;
border:1px solid red;
background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
background-size: 100% 100%;
vertical-align: top;
}
.area{
position: absolute;
width:200px;
height:200px;
background-color: rgba(0, 0, 255,.5);
visibility: hidden;
cursor: move;
}
.zoom-content{
display: inline-block;
width:500px;
height:500px;
border:1px solid red;
background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
background-repeat: no-repeat;
}
</style>
</head>
<body>
<div class="box">
<div class="area"></div>
</div>
<div class="zoom-content"></div>
<script>
// 获取DOM元素
let area = document.querySelector('.area');
let box = document.querySelector('.box');
let zoom = document.querySelector('.zoom-content');
// 蓝色背景盒子尺寸
let areaWidth = area.clientWidth;
let areaHeight = area.clientHeight;
// 图片盒子大小尺寸
let boxWidth = box.clientWidth;
let boxHeight = box.clientHeight;
// 蓝色盒子X轴极限距离
let maxX = boxWidth - areaWidth;
// 蓝色盒子Y轴极限距离
let maxY = boxHeight - areaHeight;
// 缩放倍率
let xScale = boxWidth / areaWidth;
let yScale = boxHeight / areaHeight;
// 缩放后的图片尺寸
let bgWidth = zoom.clientWidth * xScale;
let bgHeight = zoom.clientHeight * yScale;
zoom.style.backgroundSize=`${xScale * 100}% ${yScale * 100}%`;
const enter = (event) => {
area.style.visibility = 'visible';
setAreaPosition(event);
box.addEventListener("mousemove",move);
box.addEventListener("mouseleave",leave);
}
const leave = () => {
area.style.visibility = 'hidden';
box.removeEventListener("mousemove",move);
box.removeEventListener("mouseleave",leave);
}
const setAreaPosition = (event) => {
let x = event.x - areaWidth / 2;
let y = event.y - areaHeight / 2;
x = Math.min(maxX,Math.max(0,x));
y = Math.min(maxY,Math.max(0,y));
area.style.left = x+"px";
area.style.top = y+"px";
zoom.style.backgroundPosition = `${-(x / boxWidth * bgWidth)}px ${-(y / boxHeight * bgHeight)}px`;
}
const move = (event) => {
setAreaPosition(event);
}
box.addEventListener("mouseenter",enter)
</script>
</body>
</html>