(个人理解的画图在最后,审美差了点请见谅,)
- css
*{ margin: 0; padding: 0; } body>div{ width: 1200px; height: 600px; margin: 100px auto; position: relative; } #box1{ position: absolute; top: 0; left: 0; width: 600px; height: 600px; } #box1>img{ width: 100%; height: 100%; } #box1>div{ width: 200px; height: 200px; background-color: rgba(255,255,255,.2); position: absolute; top: 0; left: 0; display: none; } #box2{ width: 600px; height: 600px; position: absolute; left: 600px; top: 0; overflow: hidden; display: none; } #box2>img{ width: 1800px; height: 1800px; position: absolute; top: 0; left: 0; }
- html
<div> <div id="box1"> <img src="http://img1.imgtn.bdimg.com/it/u=2144345033,2329962120&fm=26&gp=0.jpg"> <div></div> </div> <div id="box2"> <img src="http://img1.imgtn.bdimg.com/it/u=2144345033,2329962120&fm=26&gp=0.jpg"> </div>
- js
/** * 思路: * 商品放大镜是有两个盒子,第一个盒子就是我们的可以看到的商品图片,鼠标移入有一个小盒子会显示出来跟着鼠标移动, * 同时右边第二个盒子里面也有一张图片,第一个可视盒子与其中小盒子的大小比例刚好等于第二个盒子中图片大小与第二 * 个盒子的大小比例,鼠标移入第一个商品盒子时显示其中小盒子与右侧大盒子,鼠标在盒子中移动时实时记录其事件对象 * 的clientX和clientY,如果有滚动条则是pageX和pageY,然后每一次移动计算出值给其中小盒子让其跟着鼠标移动, * 同时通过与其中小盒子宽高的比例来确定右侧盒子中的图片移动距离 */ //获取元素,两个大盒子和鼠标跟随小盒子,需要移动位置的图片 let box1=document.getElementById('box1'), box2=document.getElementById('box2'), mBox=box1.getElementsByTagName('div')[0], mImg=box2.getElementsByTagName('img')[0]; //给商品显示盒子绑定鼠标移动事件 box1.onmousemove=(ev)=>{ //需要先让两个盒子显示,如果设置了移动后在显示会有一个短暂的跳动 mBox.style.display='block'; box2.style.display='block'; //获取当前鼠标指针坐标,父盒子的xy轴偏移量,计算出鼠标指针距离商品显示盒子的距离 let x=ev.clientX, y=ev.clientY, eOffsetLeft=offset(box1)['left'], eOffsetTop=offset(box1)['top']; eX=x-eOffsetLeft; eY=y-eOffsetTop; /** * 边界判断: * 鼠标指针在跟随小盒子的中心,所以四边都有一个跟随小盒子的一般宽度是不可动的,详情见后图 */ if(eX<mBox.clientWidth/2){ eX=0 }else if(eX>box1.clientWidth-mBox.clientWidth/2){ eX=box1.clientWidth-mBox.clientWidth; }else{ eX-=mBox.clientWidth/2; } if(eY<mBox.clientHeight/2){ eY=0 }else if(eY>box1.clientHeight-mBox.clientHeight/2){ eY=box1.clientHeight-mBox.clientHeight; }else{ eY-=mBox.clientHeight/2; } mBox.style.top=eY+'px'; mBox.style.left=eX+'px'; mImg.style.top=eY*-3+'px'; mImg.style.left=eX*-3+'px'; } box1.onmouseleave=()=>{ mBox.style.display='none'; box2.style.display='none'; } /** * 获取元素距离body上边和左边的偏移量的方法 * @param ele * @returns {{top: number, left: number}} */ function offset(ele) { let left = ele.offsetLeft; // 当前元素的offsetLeft let top = ele.offsetTop; // 当前元素的offsetTop let parent = ele.offsetParent; // 获取当前元素的offsetParent while (parent && parent.nodeName !== 'BODY') { left += parent.clientLeft + parent.offsetLeft; top += parent.clientTop + parent.offsetTop; parent = parent.offsetParent; } return { left, top } }
这是比较详情比较笨重的写法,主要帮助刚学习的小白理解其中原理
下面是封装的一个放大镜插件:
*{
margin: 0;
padding: 0;
}
.readingBox>div:nth-of-type(1){
width: 100%;
height: 100%;
position: absolute;
/*设置父元素与内部图片的边距,看需求设置*/
/*left: 100px;*/
/*top: 50px;*/
}
.readingBox>div:nth-of-type(1)>img{
width: 100%;
height: 100%;
}
.readingBox>div:nth-of-type(2){
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: none;
/*显示区的位置,设置为内部图片宽度加上父元素与内部图片的左边距为left,高度同20行一样*/
top: 0px;
}
.readingBox>div:nth-of-type(1)>div:nth-of-type(1){
position: absolute;
display: none;
border: 1px solid rgba(255,255,255,0.2)
}
html
<div class="readingBox" id="box">
js
~function(){
class Reading{
constructor(obj){
this.ele=obj.ele;//创建放大镜的父元素
this.img=obj.img;//放大镜图片的地址
this.width=obj.width;//放大镜显示区的宽度
this.height=obj.height;//放大镜显示区的高度
this.init();
}
//主入口
init(){
this.createEle();
this.bindMouse();
}
//创建获取元素
createEle(){
this.ele.style.width=this.width+"px";
this.ele.style.height=this.height+"px";
this.ele.style.position='relative';
let str=`<div ><img src="${this.img}">
<div style="width: ${this.width/3}px;height: ${this.height/3}px;"></div>
</div>
<div style="left:${this.width}px"><img src="${this.img}" width="${this.width*3}px" height="${this.height*3}px" style="position: absolute"></div>`;
this.ele.innerHTML=str;
this.eDivBox=this.ele.getElementsByTagName('div')[0];
this.eImgBox=this.ele.getElementsByTagName('div')[2];
this.readDiv=this.ele.getElementsByTagName('div')[1];
this.eImg=this.ele.getElementsByTagName('div')[2].getElementsByTagName('img')[0];
}
//为父盒子绑定鼠标移入移除和移动的事件
bindMouse(){
this.eDivBox.onmouseenter=()=>{
this.readDiv.style.display='block';
this.eImgBox.style.display='block';
};
this.eDivBox.onmouseleave=()=>{
this.readDiv.style.display='none';
this.eImgBox.style.display='none';
};
this.eDivBox.onmousemove=(ev)=>{
let left=ev.pageX-this.eDivBox.offsetLeft,top=ev.pageY-this.eDivBox.offsetTop;
//判断边界
let ban=this.readDiv.offsetWidth/2;
left=left<ban?ban:left+ban>this.eDivBox.offsetWidth?this.eDivBox.offsetWidth-ban:left;
top=top<ban?ban:top+ban>this.eDivBox.offsetHeight?this.eDivBox.offsetHeight-ban:top;
console.log(left, top);
this.readDiv.style.left=left-ban+'px';
this.readDiv.style.top=top-ban+'px';
this.eImg.style.left=-3*(left-ban)+'px';
this.eImg.style.top=-3*(top-ban)+'px';
}
}
}
new Reading({ele:box,img:'img/timg6A2U91M4.jpg',width:600,height:600})
}();