案例简述
这次案列是模仿京产品详情页中,产品图放大的效果。
简单说下效果的具体步骤:
1.鼠标经过预览区时,遮盖层和产品大图显示;鼠标离开则隐藏
2.遮盖层跟随鼠标进行移动,并且遮盖层只在预览区域内移动,超出范围位置则不动
3.大图中产品位置跟随遮盖层的位置变化。换句话说就是大图中产品的细节部分与遮盖层聚焦的产品细节与之对应。
先看下京东原版的效果
案例实现的整体思想
第一部分:鼠标经过和离开预览区,遮盖层和大图片显示或隐藏。
这部分主要是给预览区添加侦听器:两个鼠标事件mouseover、mouseleave,对遮盖层和大图片的display进行控制。
第二部分:遮盖层跟随鼠标移动而移动。
第二部分的内容是比较复杂的,是最重要的部分。mousemove事件。首先来分析一下,要想遮盖层跟随鼠标移动,其核心思想就是获得鼠标在预览区的坐标,并把鼠标实时更新的坐标值赋值给遮盖层的left和top值。
第二部分的完成主要分为三个步骤:a. 给预览区添加鼠标移动的侦听器,同时立即获得鼠标当前在预览区的位置,使用e.pageX - 预览区.offsetLeft 得到鼠标在预览区的水平位置,垂直位置同理。b. 再来确定遮盖层的偏移量,把a中的鼠标的位置赋值给遮盖层。如果直接赋值的话,鼠标在遮盖层的左上角,为了让鼠标在遮盖层的中心位置,在设置遮盖层的位置时,需要减去遮盖层自身宽\高的一半。c. 最后一步,还要判断遮盖层偏移量的范围,不能超出预览区。
第三部分:设置大图片的偏移量
这部分有个公式也算是个算法:遮挡层移动位置/遮挡层最大移动位置 = 大图片移动位置/大图片最大移动位置。按比例移动
掌握公式,剩下的就是计算问题了。要注意的是,根据公式算出来的数据赋值给大图片时要取反,就是取负值。
ok,以上就是本次案例的整个制作思路。有很多细节的地方,要自己去测试才能发现的。更详细的步骤我在JS代码部分里面有注释。
代码
重点部分:JS
window.addEventListener('load', function () {
// 放大镜效果
// 1.鼠标经过区域 遮挡层和大图片显示和隐藏
// 2.鼠标移动 遮挡层跟着移动 主要是获得鼠标移动时不断变化的位置赋值给遮挡层
// 3.遮挡层与大图片位置与之对应 按比例移动
// 1.鼠标经过preview_img时 遮挡层和大图片显示 和 隐藏
// 获取事件源
var preview_img = this.document.querySelector('.preview_img');
var mask = this.document.querySelector('.mask');
var big = this.document.querySelector('.big');
// 注册事件
preview_img.addEventListener('mouseover', function () {
mask.style.display = 'block';
big.style.display = 'block';
})
preview_img.addEventListener('mouseleave', function () {
mask.style.display = 'none';
big.style.display = 'none';
})
// 2.鼠标移动 更新遮挡层的位置
// 给区域添加侦听器,只要鼠标一移动 就更新遮挡层的位置 切记:只有开启定位的盒子 才可以使用left和top值
preview_img.addEventListener('mousemove', function (e) {
// (1) 经过时 就要获得鼠标在preview_img里面的坐标
var mouseX = e.pageX - preview_img.offsetLeft;
var mouseY = e.pageY - preview_img.offsetTop;
// console.log(mouseX, mouseY);
// (2) 更新遮挡层的位置
// a.如果直接赋值的话:鼠标是在遮挡层的左上角,为了美观鼠标应该在遮挡层的中心位置 - 盒子高\宽的一半
var maskX = mouseX - mask.offsetWidth / 2;
var maskY = mouseY - mask.offsetHeight / 2;
// b.此时还会出现一个问题:遮挡层在preview_img区域之外也出现了 我们只需要在区域内显示 区域外不显示
// 所以 我们需要一个判断条件 left的最大值(previwe_img.width-mask.width)和最小值(0)
var maskMax = preview_img.offsetWidth - mask.offsetWidth;
if (maskX <= 0) {
maskX = 0;
} else if (maskX >= maskMax) {
maskX = maskMax;
}
if (maskY <= 0) {
maskY = 0;
} else if (maskY >= maskMax) {
maskY = maskMax;
}
mask.style.left = maskX + 'px';
mask.style.top = maskY + 'px';
// console.log(mask.style.left, mask.style.top);
// 3.大图片跟随遮挡层的移动而移动
// 有一个核心算法: 遮挡层移动位置/遮挡层最大移动位置 = 大图片移动位置/大图片最大移动位置
// 遮挡层移动位置:maskX maxkY; 遮挡层最大移动位置:maskMax
// 大图片移动位置: bigX bigY; 大图片最大移动位置:bigMax
// (1)bigMax = 图片尺寸-装图片盒子的尺寸 图片比盒子大
var bigImg = document.querySelector('.bigImg');
var bigMax = bigImg.offsetWidth - big.offsetWidth;
// (2) bigX = 遮挡层移动位置 * 大图片最大移动位置 / 遮挡层最大移动位置
var bigX = maskX * bigMax / maskMax;
var bigY = maskY * bigMax / maskMax;
// (3) 大图片的left和top值: big系列的值 的负值
bigImg.style.left = -bigX + 'px';
bigImg.style.top = -bigY + 'px';
})
})
搭建结构:一定要记得引入css文件和js文件
<div class="preview_wrap ">
<div class="preview_img">
<img src="upload/s3.png" alt="">
<!-- 遮挡层 -->
<div class="mask"></div>
<!-- 放大版的图片 -->
<div class="big">
<img src="upload/big.jpg" alt="" class="bigImg">
</div>
</div>
</div>
样式:
.preview_wrap {
width: 400px;
height: 590px;
}
.preview_img {
position: relative;
height: 398px;
border: 1px solid #ccc;
}
.mask {
display: none;
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background: #FEDE4F;
opacity: .5;
border: 1px solid #ccc;
cursor: move;
}
.big {
display: none;
position: absolute;
left: 410px;
top: 0;
width: 500px;
height: 500px;
background-color: pink;
z-index: 999;
border: 1px solid #ccc;
overflow: hidden;
}
.big img {
position: absolute;
top: 0;
left: 0;
}
最后附上我的效果图。
end!
加油加油,每天进步一点点。同时也要每天给自己一点放松的时间,身体和灵魂总要有一个在路上。
好看的皮囊千篇一律,有趣的灵魂万里挑一,我想渐渐的、慢慢的变成那个万里挑一的人。