商品图片放大效果实现指南

   本文摘要

       本文介绍了实现商品图片放大镜效果的HTML/CSS/JavaScript方案。通过左右两个等比例容器,左侧显示原图并添加半透明遮罩层(mask),右侧显示放大图。当鼠标在左侧移动时,mask跟随鼠标位置,右侧图片相应移动展示放大区域。主要技术点包括:

1)使用transform使mask中心对准鼠标;

2)计算边界范围防止mask溢出;

3)通过坐标转换实现放大图同步移动。

        该方案利用事件监听和CSS定位,实现了电商网站常见的商品细节展示功能。


        在电商网站中,常见一种交互效果:当鼠标悬停在商品主图上时,右侧会同步显示放大后的商品细节。实现这一效果需要三个核心元素:

  1. 两个等比例的1:1矩形框,分别位于页面左右两侧

  2. 左侧矩形框中嵌套一个较小的矩形框(用于鼠标追踪)

  3. 一张1:1比例的商品图片作为展示内容

        当用户在左侧商品图中移动浅色追踪框时,右侧展示区域会自动同步显示对应的放大细节。

       

1.图片交互效果说明

1.1HTML结构

  • 左侧图片容器:leftbox

  • 右侧图片容器:rightbox

  • 遮罩层:mask(浅色矩形)

1.2交互逻辑

  1. 鼠标移入事件

    • leftbox添加mouseover事件

    • 触发时,将maskdisplay属性从none改为block

  2. 遮罩跟随鼠标

    • mask绑定mousemove事件

    • 计算mask位置:

      • left = pageX - leftbox.clientWidth

      • top = pageY - leftbox.clientHeight

  3. 边界处理

    • 左侧/顶部边界:

      • lefttop小于mask宽度一半时,设为0

    • 右侧/底部边界:

      • left + mask宽度/2 > leftbox宽度时,left = leftbox宽度 - mask宽度/2

      • top + mask宽度/2 > leftbox高度时,top = leftbox高度 - mask宽度/2

  4. 右侧图片联动

    • 计算缩放比例:rightbox高度 / mask高度

    • rightbox图片移动量:

      • left = -mask.left * 缩放比例

      • top = -mask.top * 缩放比例

2.实现

2.1HTML

  • container:作为外层容器,可能通过 CSS 控制整体布局。

  • left-box:左侧区域,包含遮罩层和商品图片,可能用于展示商品缩略图或触发交互效果。mask:遮罩层,通常通过 CSS 设置半透明背景或 hover 效果。

  • goods:左侧商品图片,可能与右侧大图是同一张图片的不同尺寸。

  • right-box:右侧区域,展示大尺寸商品图片,可能用于细节预览。

<body>
    <div class="container">
        <div class="left-box box">
            <div class="mask"></div>
            <img class="goods" src="goods.jpg">
        </div>
        <div class="right-box box">
            <img class='big' src="goods.jpg">
        </div>
    </div>
</body>

2.2CSS

        通过为 div.box 设置 overflow: hidden 属性,可以隐藏元素超出边界的内容。同时,对 div.mask 应用 transform: translate(-50%, -50%) 样式,能够使遮罩层向上和向左各偏移自身宽度的一半,从而实现遮罩中心始终跟随鼠标位置的效果。

*{
    margin: 0;
    padding: 0;
}
div.container{
    width: 100%;
    height: 100vh;
    display: flex;
    flex-direction: row;
    gap: 20px;
    justify-content: center;
    align-items: center;
}
div.box{
    position: relative;
    width: 600px;
    height: 600px;
    border: 1px solid black;
    overflow: hidden;
}
img.goods{
    height: 600px;
}
img.big{
    position: relative;
    height: 1200px; 
}
div.mask{
    display: none;
    position: absolute;
    width: 300px;
    height: 300px;
    background-color: rgba(213, 224, 112, 0.5);
    z-index: 1;
    transform: translate(-50%,-50%);
    cursor: move;
}

2.3JavaScript

        倍数由mask和box的大小计算。

//获取dom元素
const doms={
    mask:document.querySelector('.mask'),
    leftbox:document.querySelector('.left-box'),
    rightbox:document.querySelector('.right-box'),
    bigimg:document.querySelector('.big')
}
//左侧box位置计算
let offsetTop=doms.leftbox.offsetTop;
let offsetLeft=doms.leftbox.offsetLeft;
//事件监听
doms.leftbox.addEventListener('mouseover',over)
doms.leftbox.addEventListener('mouseout',function(){
    doms.leftboxremoveEventListener('mousemove',move);
    doms.mask.removeEventListener('mousemove',over);
    doms.mask.style.display='none';
})
//鼠标进入,mask显示,为mask添加鼠标移动事件
function over(){ 
    doms.mask.style.display='block';
    doms.mask.addEventListener('mousemove',move);
}
//鼠标移动,mask移动,图片移动
function move(e){
    const {pageX,pageY}=e;
    //计算mask的top和left值
    let x=pageX-offsetLeft;
    let y=pageY-offsetTop;
    //移动范围限制
    let range={
        left:doms.mask.clientWidth/2,
        right:doms.leftbox.clientWidth-doms.mask.clientWidth/2,
        top:doms.mask.clientHeight/2,
        bottom:doms.leftbox.clientHeight-doms.mask.clientHeight/2
    }
    if(x<range.left){x=range.left}
    if(x>range.right){x=range.right}
    if(y<range.top){y=range.top}
    if(y>range.bottom){y=range.bottom}
    //修改样式
    doms.mask.style.left=x+'px';
    doms.mask.style.top=y+'px';
    doms.bigimg.style.left=-2*(x-doms.mask.clientWidth/2)+'px';
    doms.bigimg.style.top=-2*(y-doms.mask.clientHeight/2)+'px';
}

2.4最终效果

3.完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        div.container{
            width: 100%;
            height: 100vh;
            display: flex;
            flex-direction: row;
            gap: 20px;
            justify-content: center;
            align-items: center;
        }
        div.box{
            position: relative;
            width: 600px;
            height: 600px;
            border: 1px solid black;
            overflow: hidden;
        }
        img.goods{
            height: 600px;
        }
        img.big{
            position: relative;
            height: 1200px; 
        }
        div.mask{
            display: none;
            position: absolute;
            width: 300px;
            height: 300px;
            background-color: rgba(213, 224, 112, 0.5);
            z-index: 1;
            transform: translate(-50%,-50%);
            cursor: move;
        }

    </style>
</head>
<body>
    <div class="container">
        <div class="left-box box">
            <div class="mask"></div>
            <img class="goods" src="good.jpg" alt="">
        </div>
        <div class="right-box box">
            <img class='big' src="good.jpg" alt="">
        </div>
    </div>
    

    </div>
    <script>
        //获取dom元素
        const doms={
            mask:document.querySelector('.mask'),
            leftbox:document.querySelector('.left-box'),
            rightbox:document.querySelector('.right-box'),
            bigimg:document.querySelector('.big')
        }
        //左侧box位置计算
        let offsetTop=doms.leftbox.offsetTop;
        let offsetLeft=doms.leftbox.offsetLeft;
        //事件监听
        doms.leftbox.addEventListener('mouseover',over)
        doms.leftbox.addEventListener('mouseout',function(){
            doms.leftboxremoveEventListener('mousemove',move);
            doms.mask.removeEventListener('mousemove',over);
            doms.mask.style.display='none';
        })
        //鼠标进入,mask显示,为mask添加鼠标移动事件
        function over(){ 
            doms.mask.style.display='block';
            doms.mask.addEventListener('mousemove',move);
        }
        //鼠标移动,mask移动,图片移动
        function move(e){
            const {pageX,pageY}=e;
            //计算mask的top和left值
            let x=pageX-offsetLeft;
            let y=pageY-offsetTop;
            //移动范围限制
            let range={
                left:doms.mask.clientWidth/2,
                right:doms.leftbox.clientWidth-doms.mask.clientWidth/2,
                top:doms.mask.clientHeight/2,
                bottom:doms.leftbox.clientHeight-doms.mask.clientHeight/2
            }
            if(x<range.left){x=range.left}
            if(x>range.right){x=range.right}
            if(y<range.top){y=range.top}
            if(y>range.bottom){y=range.bottom}
            //修改样式
            doms.mask.style.left=x+'px';
            doms.mask.style.top=y+'px';
            doms.bigimg.style.left=-2*(x-doms.mask.clientWidth/2)+'px';
            doms.bigimg.style.top=-2*(y-doms.mask.clientHeight/2)+'px';
        }

        
    </script>
</body>
</html>

 

 

posted @ 2025-09-29 11:30  Oblique  阅读(1)  评论(0)    收藏  举报  来源