前言:
学习该特效需要掌握client、offset系列的知识,否则会有点混乱,可以看我之前写的文章精讲-offset系列、scroll系列、client系列~,再来学习该文章,这样会好很多哦~
实现原理:
首先布局上,很明显要准备两个基本的容器,一个small,一个big,还要准备两张完全相同的图片,但是尺寸不同,每个容器中放入相应大小的图片,但是小的容器中还要放入一个可以移动的遮罩。其次就是在实现上,可根据以下步骤来一步一步完成。
布局代码:
<div id="box">
<div id="small">
<img src="./images/small.png" width="350" alt="">
<div id="mask"></div>
</div>
<div id="big">
<img src="./images/big.jpg" width="800" alt="">
</div>
</div>
复制代码
代码的样式最后会贴上,不要着急~
接下来,我们注册鼠标进入事件(在box中即可):
box.onmouseover=function(){
mask.style.display='block';
big.style.display='block';
}
复制代码
注册鼠标离开事件:
box.onmouseout=function(){
mask.style.display='none';
big.style.display='none';
}
复制代码
再接下来,就是重难点了,需要好好理解与消化~
第一步: 为小的容器注册移动事件,并且让mask随着鼠标的移动而移动:
small.onmousemove=function(e){
var x = e.clientX;
var y = e.clientY;
mask.style.left = x +'px';
mask.style.top= y +'px';
}
复制代码
效果如下:
问题: 会发现鼠标跟mask并没有连在一起,而是在它的左上方,那是什么原因导致了这个问题呢?
答案:
在给box的样式设置中加了这个margin的属性,所以下面我们要把这个值减掉,此时鼠标就在mask的左上角啦~
small.onmousemove=function(e){
var x = e.clientX;
var y = e.clientY;
x = x - 50;
y = y - 50;
mask.style.left = x +'px';
mask.style.top= y +'px';
}
复制代码
第二步: 让鼠标在mask的中心位置显示:
要想实现该效果,很明显,只需要让mask向左移动自身宽度的1/2,向上移动高度的1/2即可
small.onmousemove=function(e){
var x = e.clientX-mask.offsetWidth/2;
var y = e.clientY-mask.offsetHeight/2;
x = x - 50;
y = y - 50;
mask.style.left = x +'px';
mask.style.top= y +'px';
}
复制代码
到此,会发现一直存在的一个问题:mask可以在页面的任何位置移动,显然这并不符合我们的需求,我们只需要它在small中移动。
第三步: 让mask只在small所在区域移动,不可以在这之外的区域移动
若要实现这样的效果,那必然会有一个移动的最大值,也有一个移动的最小值。当超过这个最大值时,就不可以继续移动了,而是保持这个最大值,若没有超过,就是保留当前这个值,若小于这个最小值,也不可以继续移动了,而是保持这个最小值~
为了大家更直观的理解,下面我画图来为大家解释一下:
small.onmousemove=function(e){
var x = e.clientX-mask.offsetWidth/2;
var y = e.clientY-mask.offsetHeight/2;
x = x - 50;
y = y - 50;
//最小值
x = x < 0 ? 0 : x;
y = y <0 ? 0 : y;
//最大值
x = x > small.offsetWidth-mask.offsetWidth ? small.offsetWidth-mask.offsetWidth : x;
y = y > small.offsetHeight-mask.offsetHeight ? small.offsetHeight-mask.offsetHeight : y;
mask.style.left = x +'px';
mask.style.top= y +'px';
}
复制代码
到此,mask已经不能在small之外的地方移动了,而且鼠标也在mask中心位置~
第四步: mask在small上移动,big上等比例展示相应的部分
若要实现这个效果,则要弄明白一个比例关系式,我先举个例子:
我之所以举这个例子,就是因为small与big之间也存在一个对应的比例关系,这也是放大镜特效实现的最关键的地方。
我们可以知道mask移动的距离与最大距离,也可以知道大图移动的最大距离,只需要求大图移动的距离即可!
比例: mask的移动距离/大图的移动距离=mask的最大移动距离/大图的最大移动距离
所以:大图的移动距离=mask的移动距离*大图的最大移动距离/mask的最大移动距离
以横坐标为例:
- mask的移动距离 : x
- 大图的最大移动距离 : big.children[0].offsetWidth - big.offsetWidth
- mask的最大移动距离 : small.offsetWidth - mask.offsetWidth
所以大图移动的距离就可以算出来了~
以上,第一点mask的移动距离 和第三点mask的最大移动距离上面都解释过了,但是这个大图的最大移动距离可能有些人还不能理解,那我这里来解释一下,大图的容器box的宽度没有大图的宽度大,这样就很好理解了吧~
small.onmousemove=function(e){
var x = e.clientX-mask.offsetWidth/2;
var y = e.clientY-mask.offsetHeight/2;
x = x - 50;
y = y - 50;
//最小值
x = x < 0 ? 0 : x;
y = y <0 ? 0 : y;
//最大值
x = x > small.offsetWidth-mask.offsetWidth ? small.offsetWidth-mask.offsetWidth : x;
y = y > small.offsetHeight-mask.offsetHeight ? small.offsetHeight-mask.offsetHeight : y;
mask.style.left = x +'px';
mask.style.top= y +'px';
var maskMoveMaxX = small.offsetWidth - mask.offsetWidth;
var maskMoveMaxY = small.offsetHeight - mask.offsetHeight;
var bigMoveMaxX = big.children[0].offsetWidth - big.offsetWidth;
var bigMoveMaxY = big.children[0].offsetHeight - big.offsetHeight;
var bigImgX = x * bigMoveMaxX / maskMoveMaxX;
var bigImgY = y * bigMoveMaxY / maskMoveMaxY;
}
复制代码
第五步:将大图移动的距离赋值给负margin:
这里大家可能会有疑惑, (1)为什么是负margin?
大家可以进一些购物网站看一下放大镜的效果,当mask在小图上向右移动时,其实大图是向左移动的,则方向是反的,所以当然是负margin咯~
(2)那为什么要将计算的结果赋值给margin,而不是left,或者top呢?
大家可以先试一下,试一下就知道为什么了。因为我们只是给big设置了定位,它脱离了文档流,但是里面的内容并没有脱离文档流,所以left与top的值不起作用,所以我们用margin.
small.onmousemove=function(e){
var x = e.clientX-mask.offsetWidth/2;
var y = e.clientY-mask.offsetHeight/2;
x = x - 50;
y = y - 50;
//最小值
x = x < 0 ? 0 : x;
y = y <0 ? 0 : y;
//最大值
x = x > small.offsetWidth-mask.offsetWidth ? small.offsetWidth-mask.offsetWidth : x;
y = y > small.offsetHeight-mask.offsetHeight ? small.offsetHeight-mask.offsetHeight : y;
mask.style.left = x +'px';
mask.style.top= y +'px';
var maskMoveMaxX = small.offsetWidth - mask.offsetWidth;
var maskMoveMaxY = small.offsetHeight - mask.offsetHeight;
var bigMoveMaxX = big.children[0].offsetWidth - big.offsetWidth;
var bigMoveMaxY = big.children[0].offsetHeight - big.offsetHeight;
var bigImgX = x * bigMoveMaxX / maskMoveMaxX;
var bigImgY = y * bigMoveMaxY / maskMoveMaxY;
big.children[0].style.marginLeft = -bigImgX +'px';
big.children[0].style.marginTop = -bigImgY +'px';
}
复制代码
好啦,到这里所有的逻辑代码都结束啦,希望对你有所帮助~
那样式代码我这里就不贴了,大家可以去我的码云上下载下来码云
转载于:https://juejin.im/post/5cfe2e55518825225162cfbd