放大镜特效,在电商网站是比较常见的。先贴出我的代码。
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的距离后,要再减去遮罩层的一半,如果不这样,鼠标定位会在左上角,不符合视觉审美效果。
其次,应该 注意,右侧大图的位置,是根据左侧小图与大图的倍数来确定 的。
如有疑问,请留言 。