做一个类似淘宝放在图片上会将放大镜选取的局部图片放大两倍的效果
<!-- 原显示图片 -->
<div id="box">
<!-- 放大镜选取 -->
<div id="glass"></div>
</div>
<!-- 放大效果显示 -->
<div id="show"></div>
随便网上找了个图片
#box,#show{
width: 240px;
height: 263px;
border: 1px solid black;
float: left;
position: relative;
background: url(https://c-ssl.duitang.com/uploads/item/201609/01/20160901214059_cPZ5f.jpeg) no-repeat;
/* 要点1:背景图片铺满整个显示区 */
background-size: 100%;
}
#glass{
/* 要点2:放大镜长宽为显示区比例的多少,后面效果区要相应放大多少
如此处放大镜为原来的1/4,那效果区的背景为400% */
width: 25%;
height: 25%;
background-color: transparent;
border: 1px solid red;
position: absolute;
top: 0;
left: 0;
}
#show{
/* 要点2: 效果区背景放大需与上面的比例一致 */
background-size: 400%;
}
const box = document.getElementById('box');
const show = document.getElementById('show');
const glass = document.getElementById('glass');
const [leftSide,topSide] = [box.offsetLeft,box.offsetTop];
box.onmousemove = function(e){
// 放大镜是随鼠标移动的,需要根据鼠标位置来设置放大镜左上点的坐标,
// pageX/pageY:鼠标在页面中的坐标,包括了被卷去的body部分的长度
// offsetLeft/offsetTop:获取相对于父级(有css定位的元素,如果没有就是body元素)距离
// offsetWidth/offsetHeight: width/height + 左右/上下 padding+ 左右/上下 border-width
let x = e.pageX - leftSide - glass.offsetWidth/2;
let y = e.pageY - topSide - glass.offsetHeight/2;
if(x<0 || x>box.offsetWidth-glass.offsetWidth){
x = x < 0 ? 0 : box.offsetWidth-glass.offsetWidth;
};
if(y<0 || y>box.offsetHeight-glass.offsetHeight){
y = y < 0 ? 0 : box.offsetHeight-glass.offsetHeight;
};
glass.style.left = `${x}px`;
glass.style.top = `${y}px`;
// 最后在show区域利用背景图片定位展示图片,此处的倍数与前面背景图片放大倍数相关
show.style.backgroundPosition = -glass.offsetLeft*4 + 'px ' + -glass.offsetTop*4 + 'px';
}
最后来欣赏一下我们小甜甜的围笑吧
灵魂一问:为什么不用offsetX
和offsetY
?
offsetX
:事件对象与目标节点的内填充边(padding edge)在 X 轴方向上的偏移量。—— 来自MDN
官方的解释简直是太晦涩了,简单的说,offsetX
就是鼠标点击位置相对于触发事件对象的水平距离。
那这就很好理解了,相对于触发事件对象,此处是给box设置了监听,那不就是鼠标与box的距离吗?然而,box里面还有glass啊,受事件捕获机制的影响,所以如果使用了offsetX
,你会发现为什么你的放大镜不受控制,一直乱跑,感兴趣的童鞋可以自己区尝试一下。
更多关于offsetX
,详见图解JS事件坐标screenX、clientX、pageX和offsetX的区别。