仿京东PC网页商品详情的放大镜效果(原理+代码)

实现效果

黑色只不过是转gif出问题而已

  

准备工作

1. 访问该网址,理解我们要弄的放大镜效果,鼠标经过商品图片,显示一个黄色的放大选区,右边显示该选区的大图。

2. 获取商品图片和商品大图

【摩托罗拉moto X30 Pro】摩托罗拉moto X30 Pro 全新骁龙8+ 2亿像素 125W闪充+50W无线充 144Hz曲面臻彩屏 5G手机 12GB+256GB 墨韵黑【行情 报价 价格 评测】-京东

商品图片:

https://img12.360buyimg.com/n1/s450x450_jfs/t1/36890/26/19707/96919/63b05265F4b433f6c/6c7017a0c9caa09a.jpg

 商品大图:

https://img12.360buyimg.com//n0/jfs/t1/36890/26/19707/96919/63b05265F4b433f6c/6c7017a0c9caa09a.jpg

代码实现

ps: 标红的地方需要懂

1、项目结构:

​ 

2、简单的网页布局

只需要准备左边一个正方形盒子右边一个大正方形盒子即可

3、商品大图在右边大盒子局部显示

商品大图不要设置宽高属性,保留其大图800*800的尺寸,商品大图在右边大盒子局部显示大图比右盒子大,父盒子 overflow:hidden

效果: 

<body>
    <div class="left-box">
        <img src="./images/small.jpg" alt="">
        <div class="right-box">
            <img src="./images/big.jpg" alt="">
        </div> 
    </div>
</body>
* {
    margin: 0;
    padding: 0;
    /* 盒子模型:padding和边框都不会撑大盒子 */
    box-sizing: border-box;
}

.left-box {
    position: relative;
    margin-top: 100px;
    margin-left: 100px;
    width: 400px;
    height: 400px;
    border: 1px solid #ccc;
}

.left-box>img{
    width: 100%;
}

.right-box {
    position: absolute;
    top: 0;
    left: 400px;
    width: 540px;
    height: 540px;
    border: 1px solid #ccc;
    /* big-box 下的img不设置宽高,就是显示大图本身大小 800*800 */
    /* 父盒子局部显示大图 */
    overflow: hidden;
}

4、放大镜选区效果布局

选区在左边盒子里,所以是左边盒子儿子,透明度 opacity: 0.5; 鼠标的样式要变成移动的 cursor: move;

5、放大镜选区 和 右侧大盒子 隐藏

隐藏 display: none;(不保留空间)

6、鼠标经过左边的盒子,显示放大镜选区 和 右侧大盒子。

使用js注册监听鼠标经过mouseover和鼠标离开mouseout事件 addEventListener('mouseover', function() {})

7、选区的移动位置1

放大镜选区跟随鼠标移动,鼠标的移动范围是在左边盒子里,不是在放大镜选区里,所以应该是左边的盒子注册监听鼠标移动事件 addEventListener('mousemove', function() {})


放大镜选区跟随鼠标移动,已知:

  • mousemoveevent对象存在属性pageXpageY,表示当前鼠标在整个网页页面中的位置。
  • 标签元素存在属性offsetLeftoffsetTop,表示当前元素的位置(相对于有定位的父级,如果不存在有定位的父级,则是body)。
  • 标签元素存在属性offsetWidthoffsetHeight,表示当前元素的大小,宽度和高度。
  • 标签元素存在属性style,若想改变有定位标签元素的位置,则修改元素的style.leftstyle.top
  • 标签元素的位置,以左基点计算。

计算,求 左盒子里的鼠标相对于左盒子的位置(style.leftstyle.top

放大镜选区的盒子 在 左盒子中 的位置  (鼠标在选区盒子左基点)=  当前鼠标在整个网页页面中的位置 - 左盒子的位置

8、选区的移动位置2

放大镜选区跟随鼠标移动优化1: 把鼠标放在放大镜选区的中间(鼠标在页面中的位置不变,把选区盒子往左移动一半,往上移动一半


计算: 选区的移动距离 = 放大镜选区的盒子 在 左盒子中 的位置(鼠标在选区盒子中间) =  放大镜选区的盒子 在 左盒子中 的位置  (鼠标在选区盒子左基点) -(放大镜选区的大小 / 2)


 

9、选区的移动范围

放大镜选区跟随鼠标移动优化2,限制选区盒子的移动范围:第8步的移动,会出现选区盒子超出左盒子的现象,所以我们要限制选区盒子的移动范围,这时候鼠标就不需要在放大镜选区中间了。小于最小范围,则使它等于最小范围,超过最大范围,则使它等于最大范围。

超过的图:

限制以后:


范围计算:

最小:选区盒子距离左盒子左边框为0

最大:选区盒子距离左盒子右边框为0,即 左盒子的宽度-选区盒子的宽度


  

选区的移动:

10、右盒子的大小优化。

放大镜选区以后,右盒子显示大图中的相应区域,再这里要构成一种比例关系(因为是正方形,所以就不写高度宽度,直接写大小):


比例1(显示的比例):选区的大小/左盒子的大小 = 右盒子的大小/大图的大小


所以,css中的已知选区盒子大小 250 、左盒子大小400 、大图大小800,则右盒子的大小为250*800/400 = 500,我们之前布局写了540,所以要改成500;

11、大图的移动

放大镜选区以后,右盒子显示大图中的相应区域,所以应该是大图本身相对着父盒子在移动,为了与放大镜选区一致,所以这里也存在一种比例关系:


比例2(移动距离的比例):选区的移动距离/选区的最大移动距离 =  大图的移动距离 / 大图的最大移动距离

大图的移动距离 = 选区的移动距离 * 大图的最大移动距离 / 选区的最大移动距离

大图的最大移动距离:大图距离右盒子右边框为0,即 大图的宽度-右盒子的宽度


注意别忘了,给右盒子大图做定位,大图才能相对右盒子进行移动。

因为是大图相对着右盒子移动,所以要用负号,大图的区域才会在父盒子中显示。

总结

重点是要知道第7步中的已知,以及计算鼠标在盒子中的位置(相对位置),以及理解两个比例关系,这两个比例关系就是等比放大效果的原因,最后就是css也挺重要的,理解相对定位,配合css,js才能作出特效。

完整代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>仿京东PC网页商品详情的放大镜效果</title>
    <link rel="stylesheet" href="./css/index.css">
    <script src="./js/magnifier.js"></script>
</head>
<body>
    <div class="left-box">
        <img src="./images/small.jpg" alt="">
        <div class="magnifier-box"></div>
        <div class="right-box">
            <img src="./images/big.jpg" alt="" class="bigImg">
        </div> 
    </div>  
</body>
</html>
* {
    margin: 0;
    padding: 0;
    /* 盒子模型:padding和边框都不会撑大盒子 */
    box-sizing: border-box;
}

.left-box {
    position: relative;
    margin-top: 100px;
    margin-left: 100px;
    width: 400px;
    height: 400px;
    border: 1px solid #ccc;
}

.left-box>img{
    width: 100%;
}

.right-box {
    position: absolute;
    top: 0;
    left: 400px;
    width: 500px;
    height: 500px;
    border: 1px solid #ccc;
    /* right-box 下的img不设置宽高,就是显示大图本身大小 800*800 */
    /* 父盒子局部显示大图 */
    overflow: hidden;
    display: none;
}

.right-box>img {
    position: absolute;
}

.magnifier-box {
    position: absolute;
    top: 0;
    left: 0;
    width: 250px;
    height: 250px;
    background: rgb(240, 221, 48);
    border: 1px dashed rgb(240, 221, 48);
    /* 整个盒子的透明度 */
    opacity: 0.5;
    /* 鼠标样式变成移动的 */
    cursor: move;
    display: none;
}
// 因为script在DOM之前引入,所以代码要写在onload事件里
// onload:等页面完全加载以后再执行
window.addEventListener('load',function(){
    // 左盒子
    var left = document.querySelector('.left-box');
    // 右盒子
    var right = document.querySelector('.right-box');
    // 放大镜选区
    var magnifier = document.querySelector('.magnifier-box');
    // 鼠标经过 显示
    left.addEventListener('mouseover',function(){
        magnifier.style.display = 'block';
        right.style.display = 'block';
    })
    // 鼠标离开 隐藏
    left.addEventListener('mouseout',function(){
        magnifier.style.display = 'none';
        right.style.display = 'none';
    })
    // 鼠标移动
    left.addEventListener('mousemove',function(event){
        // console.dir(left);
        // 放大镜选区的移动位置(鼠标在选区左基点)
        let magnifierX = event.pageX - left.offsetLeft;
        let magnifierY = event.pageY - left.offsetTop;
        // 放大镜选区的移动位置(鼠标在选区中间)
        let magnifierCenterX = magnifierX - (magnifier.offsetWidth / 2);
        let magnifierCenterY = magnifierY - (magnifier.offsetHeight / 2);
        // 放大镜选区的最大移动距离,因为是正方形,所以计算一个就行
        let magnifierMaxRangeX = left.offsetWidth - magnifier.offsetWidth
        // let maxRangeY = left.offsetHeight - magnifier.offsetHeight
        // 限制选区移动范围,宽高都要设置
        if(magnifierCenterX < 0) {
            magnifierCenterX = 0
        }
        if(magnifierCenterX > magnifierMaxRangeX) {
            magnifierCenterX = magnifierMaxRangeX
        }
        if(magnifierCenterY < 0) {
            magnifierCenterY = 0
        }
        if(magnifierCenterY > magnifierMaxRangeX) {
            magnifierCenterY = magnifierMaxRangeX
        }
        // 放大镜选区的移动
        magnifier.style.left = magnifierCenterX  + 'px';
        magnifier.style.top = magnifierCenterY + 'px';
        // 大图
        let bigImg = document.querySelector('.bigImg');
        // 大图的最大移动距离
        let bigImgXMaxRange = bigImg.offsetWidth - right.offsetWidth
        // 大图的移动位置
        let bigImgX = magnifierCenterX * bigImgXMaxRange / magnifierMaxRangeX 
        let bigImgY = magnifierCenterY * bigImgXMaxRange / magnifierMaxRangeX
         // 大图的移动
        bigImg.style.left = -bigImgX  + 'px';
        bigImg.style.top = -bigImgY + 'px';
    })
})

猜你喜欢

转载自blog.csdn.net/weixin_43991241/article/details/128799202