需求:
鼠标滑过缩略,会显示一个滑块,右侧出现滑块对应的大图部分,就是购物网站商品详情的放大镜效果。
思路:
- 首先显示缩略图abbre,缩略图上有一个滑块mark
- 缩略图的右侧是与其对应的具体放大的部分detail,放大的盒子对应着大图片detaiIImg
事件:
- 鼠标移入缩略图abbre,滑块mark和放大部分detail显示
- 鼠标移动,可以控制滑块mark在缩略图abbre上的移动
- 滑块mark移动的距离不能超出缩略图abbre的范围
- 同时还需要控制大图片detaiIImg在放大部分detail中的移动。
用到的数值:
- 缩略图abbre的尺寸:300 * 200
- 滑块mark尺寸:50 * 50
- 放大部分detail尺寸:300 * 300
- 大图detaiIImg尺寸:
- 计算公式 : mark / abbre = detail / detaiIImg
- detaiIImg = detail /(mark / abbre)
事件:
- 鼠标移入缩略图abbre,显示滑块mark和放大部分detail
- 移动滑块mark的位置,控制大图在放大部分的移动(鼠标处于滑块的中间位置)
- 滑块的位置: mark = 鼠标的位置 = abbre - mark / 2
- 且mark不可以超出abbre的范围:
- 最小top / left : 0
- 最大top / left : abbre - mark
- 大图的位置:
- 滑块mark在缩略图abbre中移动的距离A
- 大图detaiIImg要移动的距离B
- A / abbre = B / detaiIImg
- B = (A / abbre) * detaiIImg
- 大图移动的方向和滑块mark是相反的
- 鼠标移出缩略图abbre,隐藏滑块mark和放大部分detail
代码
<style>
.magnifier {position: relative;}
.abbre {position: relative;width: 300px;height: 200px;}
.abbre img {display: block;width: 100%;height: 100%;}
.abbre .mark {position: absolute;top: 0;left: 0;width: 50px;height: 50px;
background: rgba(255, 255, 255, .4);cursor: move;}
.detail {position: absolute;top: 0;left: 300px;width: 300px;height: 300px;
overflow: hidden;display: none;}
.detail img {position: absolute;}
</style>
<section class="magnifier">
<!-- 缩略图 -->
<div class="abbre">
<img src="1.jpg" alt="">
<!-- MARK遮罩层 -->
<div class="mark"></div>
</div>
<!-- 放大部分 -->
<div class="detail">
<!-- 大图 -->
<img class="detailImg" src="1.jpg" alt="">
</div>
</section>
<!-- 需要引入jquery-->
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<script>
$(function() {
// 获取需要操作的元素
let $magnifier = $(".magnifier"), //放大镜父元素
$abbre = $magnifier.find(".abbre"), //缩略图
$mark = $magnifier.find(".mark"), //滑块
$detail = $magnifier.find(".detail"), //放大的部分
$detailImg = $magnifier.find(".detailImg"); //大图
// 按照比例算出大图的尺寸
let markW = $mark.width(), //滑块的宽
markH = $mark.height(), //滑块的高
abbreW = $abbre.width(), //缩略图的宽
abbreH = $abbre.height(), //缩略图的高
imgWidth = 0, //大图的宽
imgHeight = 0, //大图的高
detailW = $detail.width(), //放大部分的宽
detailH = $detail.height(), //放大部分的高
abbreOffset = $abbre.offset(); //滑块的偏移
// 动态计算出大图的宽高
imgWidth = (detailW * abbreW) / markW;
imgHeight = (detailH * abbreH) / markH;
// 为大图重新设置样式
$detailImg.css({
"width": imgWidth + "px",
"height": imgHeight + "px"
});
// 计算Mark和大图移动的位置
const computed = function(ev) {
// 计算Mark移动的位置:ev.pageX / ev.pageY 鼠标的位置
let curL = ev.pageX - abbreOffset.left - markW / 2,
curT = ev.pageY - abbreOffset.top - markH / 2;
// 边界处理
let minL = 0,
maxL = abbreW - markW,
minT = 0,
maxT = abbreH - markH;
curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
// 缩略框样式的时时修改
$mark.css({
"left": curL,
"top": curT
});
// 大图样式的时时修改
$detailImg.css({
"left": -curL / abbreW * detailW,
"top": -curT / abbreH * detailH
});
};
// 添加事件
$abbre.mouseenter(function(ev) {
// 鼠标移入,显示大图
$mark.css("display", "block");
$detail.css("display", "block");
computed(ev);
})
.mousemove(function(ev) {
computed(ev);
})
.mouseleave(function(ev) {
// 鼠标移出,隐藏大图
$mark.css("display", "none");
$detail.css("display", "none");
});
});
</script>