原生js实现放大镜功能,可切换图片
放大镜主要用到的的算法性问题以及思路
移动的元素是mask和大盒子的背景图
1.mask的移动和大盒子的背景图移动是有一定比例的
mask的宽 小图片的宽
-------- = ----------
bigBox的宽 大图片的宽
left mask的宽
----- = --------
x bigBox的宽
高同理
2.mask的移动和大盒子的背景图移动是反向的
3.越界
实现的效果如下:

html代码:
<!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> <link rel="stylesheet" href="style.css"> </head> <body> <div class="box"> <div class="show"> <img src="img/1.jpg" alt=""> <div class="mask"></div> </div> <!-- 图片列表 --> <ul class="list"> <li class="active"><img src="img/1.small.jpg" alt=""></li> <li><img src="img/2.small.jpg" alt=""></li> <li><img src="img/3.small.jpg" alt=""></li> <li><img src="img/4.small.jpg" alt=""></li> </ul> <div class="glass"> </div> </div> </body> </html> <script src="amp.js"></script> <script> let oBox = document.querySelector(".box"); let arr = [{ big: '1.jpg', normal: "1.jpg", small: '1.small.jpg', }, { big: '2.jpg', normal: "2.jpg", small: '2.small.jpg', }, { big: '3.jpg', normal: "3.jpg", small: '3.small.jpg', }, { big: '4.jpg', normal: "4.jpg", small: '4.small.jpg', }, ]; let setAmplify = new Amplify(oBox, arr); setAmplify.init(); </script>
CSS代码:
* { margin: 0; padding: 0; } body { height: 6000px; } ul, li, ol { list-style: none; } img { width: 100%; height: 100%; display: block; } .box { width: 1200px; position: relative; margin: 40px auto; display: flex; flex-direction: column; } .box .show { width: 400px; height: 400px; border: 2px solid red; position: relative; } .box .show .mask { width: 200px; height: 200px; background: lightpink; opacity: .4; position: absolute; left: 0; top: 0; } .box .list { width: 20%; flex: 1; display: flex; justify-content: flex-start; align-items: center; } .box .list li { margin: 20px 20px 0 0; width: 180px; height: 120px; } .box .glass { width: 400px; height: 400px; border: 2px solid black; position: absolute; left: 450px; top: 0; background: url('img/1.jpg') no-repeat 0 0; background-size: 1600px; } .box .list li.active { border: 3px solid red; }
JS代码:
// 放大镜封装类 // 参数1,执行放大镜效果的区域 // 参数2,是图片数据信息数组 class Amplify { constructor(ele, imgArray) { // 接收存储参数 this.ele = ele; this.imgArray = imgArray; // 通过参数1,也就是整个放大镜区域,来获取标签对象 // 图片区域 this.show = ele.querySelector('.show'); // 图片区域中的遮盖层 this.mask = ele.querySelector('.mask'); // 下方小图片列表中的li标签 this.list = ele.querySelectorAll('.list li'); // 放大镜区域 this.glass = ele.querySelector('.glass'); // 获取show当中的图片标签 this.img = this.show.querySelector('img'); } // 定义一个方法,来调用之后定义的所有的方法 // 入口函数 init() { this.overOut(); this.move(); this.toggle(); } // 鼠标的移入移出 overOut() { // 鼠标移入,图片区域show,让遮盖层和放大镜显示 this.show.addEventListener('mouseover', () => { this.mask.style.display = 'block'; this.glass.style.display = 'block'; }) // 鼠标移出,图片区域show,让遮盖层和放大镜隐藏 this.show.addEventListener('mouseout', () => { this.mask.style.display = 'none'; this.glass.style.display = 'none'; }) } // 鼠标移动效果 // 鼠标在 图片区域移动 时 // 1,让遮盖层,跟随鼠标移动 --- 类似之前鼠标拖拽的效果 move() { // 鼠标在show区域移动 // 不是拖拽,没有点击事件 // 移动出图片区域,遮盖层不显示,也不用写取消效果 this.show.addEventListener('mousemove', (e) => { // 1,定位 遮盖层 // 通过 鼠标的定位位置,来计算 遮盖层 左上角 定位的坐标位置 // 相对于页面窗口 - div的外边距 - div的边框线 - 遮盖层宽高的一半 // 1,如果没有页面滚动,使用相对视窗窗口 clientX 和 相对页面 PageX 是都可以的 // 如果有页面滚动,要看放大镜部分,是否跟随页面一起运动 // 如果一起运动,就使用 pageX // 如果没有一起运动,就使用 clientX // 2,offsetLeft , div与定位父级的间距,当前也就是与body的间距 // 3,clientLeft , div的边框线 // 4,遮盖层宽高的一半 , 定位之后 , 鼠标位置与遮盖层中心重合 // 我们之前使用的获取占位,有问题,如果标签是隐藏的,无法获取占位 // 只能使用获取宽度高度的方法 // clientWidth offsetHeight 获取的是占位,如果是 display:none 占位是 0 // 只能通过获取标签css属性属性值来获取 let x = e.pageX - this.ele.offsetLeft - this.ele.clientLeft - this.mask.clientWidth / 2; let y = e.pageY - this.ele.offsetTop - this.ele.clientTop - this.mask.clientHeight / 2; // 2,设定边界值 // 最小是 0 最大值 父级div宽高 - 遮盖层宽高 if (x < 0) { x = 0; } if (y < 0) { y = 0; } if (x > this.show.clientWidth - this.mask.clientWidth) { x = this.show.clientWidth - this.mask.clientWidth; } if (y > this.show.clientHeight - this.mask.clientHeight) { y = this.show.clientHeight - this.mask.clientHeight; } // 3,将数值定位给遮盖层 this.mask.style.left = x + 'px'; this.mask.style.top = y + 'px'; // 4,需要让右侧放大镜的背景图片也一起移动 // 给背景图片添加定位 // 左侧是 图片不动,遮盖层动 遮盖层动 100 100 // 右侧是 放大镜不动,背景图片动 背景图动 -100 -100 // 移动时,定位必须是按照比例来设定 // 背景图片定位 = 背景图片大小 * 遮盖层定位 / 图片大小 // 通过遮盖层移动的比例,来计算,背景图片定位的数值 // 按照比例计算背景图片的定位 // 背景图片定位 = 背景图片大小 * 遮盖层位移 / show的大小 // show的大小,背景图片大小,都应该是通过JavaScript方法获取的数据 // 可以获取宽高占位,可以是获取css样式 let bx = 1600 * x / 400; let by = 1600 * y / 400; // 给背景图片定位 // 给背景图片进行定位赋值操作 // 背景图片定位:应该是 background-position : x轴定位 y轴定位 // 使用JavaScript语法,定义 标签.style.backgroundPosition = 数值拼接px单位 数值拼接px单位 // 使用模板字符串来解析变量 // 也可以使用字符串拼接方式 bx + 'px' + ' ' + by + 'px' this.glass.style.backgroundPosition = ` -${bx}px -${by}px `; // 要完美实现放大镜效果 // 必须注意2个比例 // 1,CSS样式的比例 : 图片区域大小 : 遮盖层大小 = 背景图片大小 : 放大镜区域大小 // 2,定位的比例 : 遮盖层定位 : 图片区域大小 = 背景图片定位 : 背景图片大小 }) } // 切换效果 // 1,给当前 点击click / 鼠标经过mouseover 的标签,添加样式 // 给所有的标签去除样式,给当前点击/经过标签,添加样式 toggle() { this.list.forEach((item, key) => { item.addEventListener('click', () => { // 1,给所有的li标签清除样式 this.list.forEach((i, k) => { i.className = ''; }) // 2,给当前的标签添加样式 item.className = 'active'; // 3,设定图片 // 当前标签的索引下标 key 就是对应 图片数组中,需要显示的图片的索引下标 // 图片的实参,存储在 this.imgArray 中 通过索引下标,可以获取到对应的图片信息 // this.imgArray[key] // console.log(this.imgArray[key]); // 将每一个图片的具体信息,设定给图片标签和放大镜的背景图片 // 1,给图片标签,设定路径 // 通过数组,索引,图片属性,获取对应的图片名称 // 标签.src = 赋值 或者 标签.setAttribute('src' , 属性值) 都可以 // this.img.src = `./images/${this.imgArray[key]['normal']}`; this.img.setAttribute('src', `./img/${this.imgArray[key]['normal']}`); // 2,给放大镜区域,背景图片设定路径 // 必须把关于背景图片的所有设定都重新写一遍 this.glass.style.background = `url('./img/${this.imgArray[key]['big']}') no-repeat 0 0`; this.glass.style.backgroundSize = '1600px'; }) }) } }

浙公网安备 33010602011771号