放大镜特效,在电商网站是比较常见的。先贴出我的代码。
CSS部分
<style> * { padding: 0; margin: 0; } .wrap { 880px; border: 1px solid black; margin: 50px auto; } .wrap>div { 430px; height: 430px; border: 1px solid #eee; } .middleImg { float: left; background: url("./images/imgA_2.jpg") no-repeat; position: relative; } .largeImg { float: right; background: url("./images/imgA_3.jpg") no-repeat; display: none; } .smallImg { clear: both; list-style: none; display: flex; } .smallImg li { margin: 20px 10px; } .smallImg img { vertical-align: top; border: 2px solid transparent; } .enlarge { background: url("./images/bg.png"); 231px; height: 231px; position: absolute; top: 0; left: 0; display: none; } </style>
HTML部分
<div class="wrap"> <!-- 左上正常显示的图片 --> <div id="middleImg" class="middleImg"> <!-- 遮罩层 --> <div class="enlarge" id="enlarge"></div> </div> <!-- 右边放大的图片 --> <div id="largeImg" class="largeImg"></div> <!-- 下面的缩略图 --> <ul id="smallImg" class="smallImg"></ul> </div>
JS部分
// 初始化图片数据 let imgs = { small: ["imgA_1.jpg", "imgB_1.jpg", "imgC_1.jpg"], middle: ["imgA_2.jpg", "imgB_2.jpg", "imgC_2.jpg"], large: ["imgA_3.jpg", "imgB_3.jpg", "imgC_3.jpg"] } handleSmall(); // 操作缩略图 handleMiddle(); // 操作展示图 // 用于操作缩略图的函数 function handleSmall() { // 为id为smallImg的ul动态的添加li smallImg.innerHTML = imgs.small.map((item, index) => { return `<li><a href="#"><img src="./images/${item}" _id="${index}" class="img"/></a></li>`; }).join(""); let imgArr = document.getElementsByClassName("img"); // 获取所有的img元素集合 imgArr[0].style.borderColor = "black"; // 为第一个缩略图添加border // 为id为smallImg的ul添加mouseover事件 smallImg.addEventListener("mouseover", (e) => { // 如果是在缩略图上面移动 if (e.target.nodeName === "IMG") { // 首先将所有缩略图的border去除掉 for (let i = 0; i < imgArr.length; i++) { imgArr[i].style.borderColor = "transparent"; } e.target.style.borderColor = "black"; // 然后将当前鼠标所在的缩略图上面添加上border let i = e.target.getAttribute("_id"); // 获取到该图片的id // 改变左上方图片以及右边大图的链接 middleImg.style.background = `url("./images/${imgs.middle[i]}") no-repeat` largeImg.style.background = `url("./images/${imgs.large[i]}") no-repeat` } }, false); } // 给左上方的图片添加鼠标移入移出事件的函数 function handleMiddle() { middleImg.addEventListener("mousemove", (e) => { // 鼠标移动时 右边大图以及遮罩层显示 largeImg.style.display = "block"; enlarge.style.display = "block"; // 鼠标当对于文档显示区的坐标 let mouseX = e.clientX; let mouseY = e.clientY; // middleImg 相对于文档显示区的坐标 let eleX = middleImg.offsetLeft; let eleY = middleImg.offsetTop; let moveX = mouseX - eleX - enlarge.offsetWidth / 2; let moveY = mouseY - eleY - enlarge.offsetHeight / 2; // 边界判断 if (moveX <= 0) { moveX = 0; } else if (moveX >= middleImg.clientWidth - enlarge.offsetWidth) { moveX = middleImg.clientWidth - enlarge.offsetWidth; } if (moveY <= 0) { moveY = 0; } else if (moveY >= middleImg.clientHeight - enlarge.offsetHeight) { moveY = middleImg.clientHeight - enlarge.offsetHeight } // 动态修改遮罩层的位置 enlarge.style.left = moveX + "px"; enlarge.style.top = moveY + "px"; // 动态修改大图的显示位置 largeImg.style.backgroundPositionX = -moveX * (800 / 430) + "px"; largeImg.style.backgroundPositionY = -moveY * (800 / 430) + "px"; }, false); // 鼠标移出时 右边大图以及遮罩层不显示 middleImg.addEventListener("mouseout", () => { largeImg.style.display = "none"; enlarge.style.display = "none"; }, false); }
在这个程序中,需要注意的是在确定鼠标距离事件源的位置,要减去离整个clienx和clientY的距离后,要再减去遮罩层的一半,如果不这样,鼠标定位会在左上角,不符合视觉审美效果。
其次,应该 注意,右侧大图的位置,是根据左侧小图与大图的倍数来确定 的。
如有疑问,请留言 。