由项目需要,原生写了个详情页图片放大镜的效果,扔上代码供学习分享,也作为日常笔记...
效果如图(例子中偷偷链了张天猫的图片,希望没啥事 -。-):
实现过程教简单,但我们还是从css开始分析,过程如下(图片已正方形为例):
css:
/ 图片标签 /
.mainImg{
width: 100%; / 各位大老爷们看着办,尽量100%好看些[斜眼笑] /
height: 100%; / 各位大老爷们看着办,尽量100%好看些[斜眼笑] /
}
/ 遮罩层-既放大区域 /
.glass{
position: absolute; / 必需 /
width: 50px; / 遮罩层宽度 此处是放大4倍,所以为200/4=50 /
height: 50px; / 遮罩层高度 此处是放大4倍,所以为200/4=50 /
top: -9999px; / 绝对位置,先放远些 /
left: -9999px; / 绝对位置,先放远些 /
cursor: move; / 鼠标样式,好看些 /
background: rgba(0,180,0.5); / 遮罩层样式,好看些 /
}
/ 大图所在的容器 /
.imgMax{
position: absolute; / 必需 /
overflow: hidden; / 必需,盖掉超出的大图[斜眼笑] /
left: 210px; / 必需,此处为距原图左边10像素 /
top: 0; / 必需,此处为距上边0像素 /
width: 200px; / 放大图片容器的宽度 此处此处是放大4倍,为200,保持和原图容器一般大,若此处为400,则是放大24倍,那么相应的放大图片应该是20042=1600 /
height: 200px; / 放大图片容器的高度 此处此处是放大4倍,为200,保持和原图容器一般大,若此处为400,则是放大24倍,那么相应的放大图片应该是20042=1600 /
display: none; / 先隐藏 /
}
.maxImg{
position: absolute; / 必需 /
width: 800px; / 此处是放大4倍,所以为2004=800 受放大图片所在的容器影响,规则如上 /
height: 800px; / 此处是放大4倍,所以为2004=800 受放大图片所在的容器影响,规则如上 /
}
上面css中需要注意的就是几个position和缩放比例,注意调整下即可
写完样式,来看看布局:
html:
接下来是主要的js代码,一如既往的带注解:
js:
var imgUrl = imgContainer.querySelector('.JmainImg').src.replace(/.(jpg|jpeg|png|gif)()(\d+)(x)(\d+)(q90)?/g,'');
// 取大图标签的节点
var maxImg = imgContainer.querySelector('.J_maxImg');
// 给该节点的src属性赋值为大图的url
maxImg.src = imgUrl;
// 取大图所在的容器
var maxImgContainer = imgContainer.querySelector('.J_imgMax');
// 取遮罩块
var glassBlock = imgContainer.querySelector('.J_glass');
// 取消放大镜效果
var hideMaxImg = function(){
glassBlock.style.top = '-9999px';
glassBlock.style.left = '-9999px';
maxImgContainer.style.display = 'none';
}
// 鼠标移出图片区域,取消放大镜效果
imgContainer.onmouseout = function(event){
event.stopPropagation();
hideMaxImg();
};
// 鼠标在图片区域内移动事件
imgContainer.onmousemove = function(event) {
event.stopPropagation();
// 取图片容器的大小及其相对于视口的位置,需要实时取,所以放在move事件里
var clientRect = event.currentTarget.getBoundingClientRect();
// 获取距鼠标距的上和左的坐标
var leftX = event.clientX - clientRect.left;
var leftY = event.clientY - clientRect.top;
// 动态设置遮罩块的left和top位置 这里需要减去遮罩层的一半,因为鼠标位于遮罩块中心点
var pointerLeft = leftX - 25;
var pointerTop = leftY - 25;
// 如果鼠标坐标移动超出原始图片区域边缘 则取消放大镜效果 因为这里存在快速移动鼠标到大图区域时,鼠标仍处在外层的图片区域内,并不会触发mouseout事件(虽然中间隔了小小的间距,但是快速移动仍能产生这个bug,如代码下面的图所示)
if((pointerLeft+25) > clientRect.width || pointerLeft < 0 - 25 || (pointerTop+25) > clientRect.height || pointerTop < 0 - 25){
hideMaxImg();
return !1;
};
// 遮罩块在最左边的时候,鼠标仍在图片区域内,可在遮罩块左边缘至中心线区域内移动,且这时遮罩块为距左0像素
if(pointerLeft < 0){
pointerLeft = 0;
};
// 同上 右边限制
if(pointerLeft > clientRect.width - 50){
pointerLeft = clientRect.width - 50;
};
// 同上 顶部限制
if(pointerTop < 0){
pointerTop = 0;
};
// 同上 底部限制
if(pointerTop > clientRect.height - 50){
pointerTop = clientRect.height - 50;
};
// 设置遮罩块的位置
glassBlock.style.left = pointerLeft;
glassBlock.style.top = pointerTop;
// 取遮罩快距离左边的位置和图片区域的宽高比,用于计算大图偏移距离,展示遮罩块所对应的图片区域
var percentLeft = pointerLeft/clientRect.width;
var percentHeight = pointerTop/clientRect.height;
// 设置大图偏移距离 因为其父元素存在 overflow:hidden 所以只会展示对应区块
maxImg.style.left = -(percentLeftmaxImg.clientWidth)+'px';
maxImg.style.top = -(percentHeightmaxImg.clientHeight)+'px';
};
}
var elem = document.querySelectorAll('.J_imgBox');
elem.forEach(function(item,idx){
imgZoom(item)
})
})()
补bug图:
看完后是不是觉得简直不要太简单,接下来就来理一理以上代码中能够抽取出来在平常开发中比较实用的知识点:
Element.getBoundingClientRect()
Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置
例子: