本例以vue3为主,提供一个思路,结构简单,可移植至其他框架
推荐正方形容器,比较好计算
1、div容器
一个是左侧原图及放大区域,一个是右侧放大镜
<template>
<div
id="wapper"
class="magnifier"
@mouseenter="handleZoomMouseover"
@mouseleave="handleZoomMouseout"
@mousemove="handleZoomMousemove"
>
<img class="magnifier-img" :src="$attrs?.url" alt="加载错误" /> //原图
<div id="zoom" class="magnifier-zoom"></div>//放大区域浮层
</div>
<div id="big" class="magnifier-big">//放大镜
<div id="big-pic" class="magnifier-big-pic">//图片偏移
<img class="magnifier-img" :src="$attrs?.url" alt="加载错误" />
</div>
</div>
</template>
2、核心思想
鼠标位移实时计算偏移位置,动态调整放大区域浮层,计算图片偏移量
①:鼠标移出事件
通过样式控制对放大浮层和放大镜进行隐藏
const handleZoomMouseout = (e) => {
const zoom = document.getElementById("zoom");
const big = document.getElementById("big");
if (zoom) {
zoom.style.display = "none";//放大浮层隐藏
}
if (big) {
big.style.display = "none";//放大镜隐藏
}
};
②:鼠标移入事件
Ⅰ、计算鼠标位置相对于放大图片的位置,计算出放大浮层zoom的初始边界位置(父容器是wapper)
zoomX=鼠标点x-原图容器位置x点+浮层容器宽度的1/2+浏览器窗口的x滑动位移
zoomY=鼠标点y-原图容器位置y点+浮层容器高度的1/2+浏览器窗口的y滑动位移
Ⅱ、根据zoomX,zoomY位置:zoom容器对父容器wapper四周的移动判断,并更新位置点
Ⅲ、根据zoomX,zoomY位置展示zoom放大浮层
Ⅳ、根据原图wapper位置展示big放大镜容器
Ⅴ、根据原图wapper与zoom的宽高比计算出放大图片的宽高倍数,并对图片big-pic进行放大,同时根据宽高倍数,计算出图片big-pic需要偏移的位置(margin-top:-10px代表反向距离10px)
const handleZoomMousemove = (e) => {
const wapper = document.getElementById("wapper");//组件大容器
const zoom = document.getElementById("zoom");//放大区域容器
const big = document.getElementById("big");//放大镜容器
const bigPic = document.getElementById("big-pic");//放大镜图片容器
//Ⅰ、计算鼠标位置相对于放大图片的位置,计算出放大浮层zoom的初始边界位置(父容器是wapper)
let zoomX =
e.clientX -
wapper.offsetLeft -
zoom.offsetWidth * 0.5 +
document.documentElement.scrollLeft;
let zoomY =
e.clientY -
wapper.offsetTop -
zoom.offsetHeight * 0.5 +
document.documentElement.scrollTop;
//Ⅱ、根据zoomX,zoomY位置:zoom容器对父容器wapper四周的移动判断,并更新位置点
// zoom边界的处理:即放大镜框最大可移动区域
//左边界
if (zoomX < 0) {
zoomX = 0;
}
// 右边界
if (zoomX >= wapper.offsetWidth - zoom.offsetWidth) {
zoomX = wapper.offsetWidth - zoom.offsetWidth;
}
// 上边界
if (zoomY < 0) {
zoomY = 0;
}
// 下边界
if (zoomY >= wapper.offsetHeight - zoom.offsetHeight) {
zoomY = wapper.offsetHeight - zoom.offsetHeight;
}
//Ⅲ、根据zoomX,zoomY位置展示zoom放大浮层
// 放大镜移动
if (zoom) {
zoom.style.left = zoomX + "px";
zoom.style.top = zoomY + "px";
zoom.style.display = "block";
}
//Ⅳ、根据原图wapper位置展示big放大镜容器
if (big) {
big.style.left = wapper.offsetLeft + wapper.offsetWidth + 10 + "px";
big.style.top = wapper.offsetTop + "px";
big.style.width = wapper.offsetWidth + "px";
big.style.height = wapper.offsetHeight + "px";
big.style.display = "block";
}
//Ⅴ、根据原图wapper与zoom的宽高比计算出放大图片的宽高倍数,并对图片big-pic进行放大,同时根据宽高倍数,计算出图片big-pic需要偏移的位置(margin-top:-10px代表反向距离10px)
// 放大后的图片跟随移动
if (bigPic) {
bigPic.style.width =
wapper.offsetWidth * (wapper.offsetWidth / zoom.offsetWidth) + "px";
bigPic.style.height =
wapper.offsetHeight * (wapper.offsetHeight / zoom.offsetHeight) + "px";
bigPic.style.marginLeft =
-zoomX * (wapper.offsetWidth / zoom.offsetWidth) + "px";
bigPic.style.marginTop =
-zoomY * (wapper.offsetHeight / zoom.offsetHeight) + "px";
}
};
③:鼠标移出事件
留着给各位看官二次开发,哈哈
const handleZoomMouseover = (e) => {};
3、样式
<style lang="scss" scoped>
.magnifier {
width: 100%;
height: 100%;
cursor: zoom-in;
position: relative;
box-sizing: border-box;
&-img {
width: 100%;
height: 100%;
object-fit: contain;
}
&-zoom {
width: 160px;
height: 160px;
background-color: rgba($color: #fff, $alpha: 0.5);
border: 1px solid #eee;
box-sizing: border-box;
position: absolute;
left: 0;
top: 0;
display: none;
}
&-big {
background-color: #f9fafc;
position: absolute;
box-sizing: border-box;
border: 2px solid lightgray;
top: 0px;
z-index: 3;
display: none;
overflow: hidden;
&-pic {
> img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
}
</style>
4、 运行效果
<div style="width: 300px; height: 300px">
<CMagnifier
url="https://b2b-a-szzb-pub.oss-cn-shenzhen.aliyuncs.com/2019/08/22/%E5%85%A8%E8%B2%8C%E5%9B%BE-1566458273183.jpg"
/>
</div>