实现原理
放大镜的原理用一句话概括,就是根据小图上的鼠标位置去定位大图。
原理图(以2倍放大为例)
相信原理图已经画的很明白了, 图中,左侧框是小图框,其蓝色区域为图片遮罩层(需放大区域),右侧框是整个大图目前所在区域,其蓝色区域是放大区域,设置超出隐藏,就实现了放大遮罩区域的效果。
显然,两块蓝色区域存在着某种对应关系,即遮罩的左上角位置(相对于小图,以下称 X 坐标)和放大区域(相对于大图)的左上角位置是成比例的,即放大倍数。计算出 X 坐标后,适当调整背景图的位置,使大图向反方向移动 scale 倍的 X 坐标即可。
X 坐标为(maskX,maskY),以计算 maskX 为例:
鼠标移动中会产生 e.clientX ,标识鼠标与浏览器左侧的距离,小图与浏览器左侧的距离是 left ,由于遮罩始终是一个以鼠标为中心的正方形,所以:
maskX = e.clientX - left - mask/2
同理,
maskY = e.clientY - top - mask/2
大图的对应样式设置为:
{
left: - maskX * scale + 'px';
top: - maskY * scale + 'px';
}
效果演示
我引用的ui库是elementui,因为我当时需要的是商品可以轮播在加上商品放大效果,如果是简单的商品图片放大大家百度应该方法都差不多,大致都能实现,可是我因为商品需要在x轴上轮播,就必须在css上面加 overflow-x: hidden;我看了几个轮播插件,好像都需要加,因为如果加了 overflow的话,放大的图就不能出现了,后来想了好多办法,找到一种解决办法,代码如下:
如果大家不需要轮播的话可以直接写下面的代码:
css:
.small-box{
position: relative;
}
.magnifier-zoom{
position: absolute;
top: 0;
left: 0;
}
.magnifier-layer{
position: absolute;
top: 0;
right: 0;
z-index: 1000;
overflow: hidden;
background-color: #fff;
}
.big-box{
position: absolute;
}
.magnifier{
position: relative;
width: 580px;
height: 360px;
border-radius: 8px;
}
.smallPic{
width: 580px;
height: 360px;
border-radius: 8px;
}
computed: {
bigWidth(){
return this.configs.scale * this.configs.width;
},
bigHeight(){
return this.configs.scale * this.configs.height;
}
},
mounted () {
this.$init()
},
data(){
return {
configs:{
width:570,//放大区域
height:360,//放大区域
maskWidth:210,//遮罩
maskHeight:210,//遮罩
maskColor:'rgba(25,122,255,0.5)',//遮罩样式
maskOpacity:0.6,
scale:2,//放大比例
},
imgObj: {},
moveLeft: 0,
moveTop: 0,
transformMask:`translate(0px, 0px)`,
showMagnifier:false,
showMask:false,
}
},
methods: {
$init(){
setTimeout(() => {
this.imgObj = this.$el.getElementsByClassName('small-box')[0].getBoundingClientRect();
}, 500);
},
changeshop(e){
this.showMagnifier = false;
this.showMask = false;
this.transformMask = `translate(0px, 0px)`
this.moveLeft = 0
this.moveTop = 0
},
handMove(e) {
// 动态获取小图的位置(或者监听 scroll )
let imgRectNow = this.imgObj;
let objX = e.clientX - imgRectNow.left;
let objY = e.clientY - imgRectNow.top;
// 计算初始的遮罩左上角的坐标
let maskX = objX - this.configs.maskWidth / 2;
let maskY = objY - this.configs.maskHeight / 2;
// 判断是否超出界限,并纠正
maskY = maskY < 0 ? 0 : maskY;
maskX = maskX < 0 ? 0 : maskX;
if(maskY + this.configs.maskHeight >= imgRectNow.height) {
maskY = imgRectNow.height - this.configs.maskHeight;
}
if(maskX + this.configs.maskWidth >= imgRectNow.width) {
maskX = imgRectNow.width - this.configs.maskWidth;
}
// 遮罩移动
this.transformMask = `translate(${maskX}px, ${maskY}px)`;
// 背景图移动
this.moveLeft = - maskX * this.configs.scale + "px";
this.moveTop = - maskY * this.configs.scale + "px";
},
handOut() {
this.showMagnifier = false;
this.showMask = false;
},
handOver() {
this.showMagnifier = true;
this.showMask = true;
}
},
如果不需要轮播图的话就可以不写changeshop这个方法就行,其余的都一样的
采坑结束,如果大家有更好的方法,欢迎在评论里告诉我哦~~~