原生JS实现图片放大镜效果 - 干货分享

准备工作

  1. 需要先了解JS的三个鼠标事件

    onmouseenter 鼠标进入

    onmouseleave 鼠标移出

    onmousemove 鼠标移动

    注意:鼠标移入的时候需要阻止事件的冒泡传播(ev.stopPropagation),所以不用onmouseover和onmouseout

  2. 理解盒子模型

    offsetParent:当前盒子的父级参照物

    offsetLeft / offsetTop:当前盒子距离其父级参照物的偏移量

    offsetWidth / offsetHeight:当前元素可视区域的宽高(内容的宽高+padding+border)

    scrollLeft / scrollTop:滚动条卷去的宽度/高度

  3. 区分鼠标事件对象

    ev.clientX / ev.clientY: 当前鼠标触发点距离当前窗口左上角的X/Y轴坐标

    ev.pageX / ev.pageY:当前鼠标触发点距离body(第一屏幕)左上角的X/Y轴坐标

    注意:低版本浏览器事件对象中不存在pageX/pageY

    ev.pageX = ev.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
    ev.pageY = ev.clientY + (document.documentElement.scrollTop || document.body.scrollTop)
    复制代码
  4. 如果图片是在某些盒子里,并且盒子距离左上角的距离根据浏览器窗口的大小改变,那么计算偏移量的时候就不能用ev.clientX/ev.clientY,而是需要用ev.pageX/ev.pageY

思路

  1. 布局
<div id="smallBox" class="smallBox">
    <img src="smallImg.jpg"/>
    <div class="mask" id="mask"></div>
</div>

<div class="big" id="bigBox">
    <img id="bigImg" src="bigImg.jpg" alt=""/>
</div>
复制代码
  1. 样式
.small{width:400px;height:400px}
.small img{width:100%;height:100%}
.small .mask{width: 200px; height: 200px; background: rgba(255, 255, 0, 0.4); position: absolute; left: 0; top: 0; display: none; cursor: move; }
.big{ width: 480px; height: 480px; border: 1px solid #999; position: absolute; top: 0; left: 400px; overflow: hidden; z-index:999; display: none;}
.big img{width:800px; height: 800px;}
复制代码
  1. JS逻辑

    3.1 页面加载完成后触发

    window.onload = function(){}
    复制代码

    3.2 获取操作的元素

    let small = document.getElementById("smallBox"),
        big = document.getElementById("bigBox"),
        bigImg = document.getElementById("bigImg"),
        mask = document.getElementById("mask");
    复制代码

    3.3 计算小图距离body的偏移量

    let smallLeft = small.offsetLeft,//小图距body的左偏移量
        smallTop = small.offsetTop,//小图距body的上偏移量
        smallBox = small;//临时值,用于计算小图距body的偏移量
    
    //计算小图距body的偏移量
    while(smallBox.offsetParent.nodeName !== 'BODY'){
        smallBox = smallBox.offsetParent;
        smallLeft += smallBox.offsetLeft;
        smallTop += smallBox.offsetTop;
    }
    复制代码

    3.4 设置鼠标移入/移出小图时,大图和遮罩层的隐藏和显示

    small.onmouseenter = function(){
        big.style.display = "block";
        mask.style.display = "block";
    };
    small.onmouseleave = function(){
        big.style.display = "none";
        mask.style.display = "none";
    };
    复制代码

    3.5 遮罩层随着鼠标移动

    small.onmousemove = function(event){
        event = event || window.event;
    
        //兼容低版本浏览器 - 低版本浏览器中不存在pageX和pageY
        event.pageX = event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
        event.pageY = event.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
    
        var x = event.pageX - smallLeft - mask.offsetWidth/2;
        var y = event.pageY - smallTop - mask.offsetHeight/2;
        
        mask.style.top = y + "px";
        mask.style.left = x + "px";
    }
    复制代码

    3.6 鼠标移动时不超出小图时拉回

    //水平方向的最大值
    var maxX = small.clientWidth-mask.clientWidth;
    //竖直方向的最大值
    var maxY = small.clientHeight-mask.clientHeight;
    
    //超出左侧时,拉回
    if(x<0) x=0;
    
    //超出右侧时,拉回
    if(x>maxX) x=maxX;
    
    //顶部超出
    if(y<0) y=0;
    
    //底部超出
    if(y>maxY) y=maxY;
    复制代码

    3.7 大图根据比例显示

    //比例 = 大图移动的距离/mask移动的距离 = 大图/小图
    var scale = bigImg.offsetWidth / small.offsetWidth;
    bigImg.style.marginLeft = -scale * x +"px";
    bigImg.style.marginTop = -scale * y +"px";
    复制代码

主要代码

//-------------------- HTML start --------------------
<div id="smallBox" class="smallBox">
    <img src="smallImg.jpg"/>
    <div class="mask" id="mask"></div>
</div>
<div class="big" id="bigBox">
    <img id="bigImg" src="bigImg.jpg" alt=""/>
</div>
//--------------------- HTML end ---------------------

//--------------------- CSS start --------------------
.small{width:400px;height:400px}
.small img{width:100%;height:100%}
.small .mask{width: 200px; height: 200px; background: rgba(255, 255, 0, 0.4); position: absolute; left: 0; top: 0; display: none; cursor: move; }
.big{ width: 480px; height: 480px; border: 1px solid #999; position: absolute; top: 0; left: 400px; overflow: hidden; z-index:999; display: none;}
.big img{width:800px; height: 800px;}
//--------------------- CSS end ---------------------

//--------------------- JS start --------------------
window.onload = function(){
    var small = document.getElementById("smallImg"),
        big = document.getElementById("bigBox"),
        bigImg = document.getElementById("bigImg"),
        mask = document.getElementById("imgMask"),
        smallLeft = small.offsetLeft,//小图距body的左偏移量
        smallTop = small.offsetTop,//小图距body的上偏移量
        smallBox = small;//临时值,用于计算小图距body的偏移量

    //计算小图距body的偏移量
    while(smallBox.offsetParent.nodeName !== 'BODY'){
        smallBox = smallBox.offsetParent;
        smallLeft += smallBox.offsetLeft;
        smallTop += smallBox.offsetTop;
    }

    //big和mask在鼠标移入small时显示,移出时隐藏
    small.onmouseenter = function(){
        big.style.display = "block";
        mask.style.display = "block";
    };
    small.onmouseleave = function(){
        big.style.display = "none";
        mask.style.display = "none";
    };
    small.onmousemove = function(event){
        event = event || window.event;

        //兼容低版本浏览器 - 低版本浏览器中不存在pageX和pageY
        event.pageX = event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
        event.pageY = event.clientY + (document.documentElement.scrollTop || document.body.scrollTop);

        var x = event.pageX - smallLeft - mask.offsetWidth/2;
        var y = event.pageY - smallTop - mask.offsetHeight/2;

        //水平方向的最大值
        var maxX = small.clientWidth-mask.clientWidth;
        //竖直方向的最大值
        var maxY = small.clientHeight-mask.clientHeight;
        if(x<0){
            //相当于超出左侧,超出左侧时,拉回
            x=0;
        }
        //超出右侧时拉回
        if(x>maxX){
            x=maxX;
        }
        //顶部超出
        if(y<0){
            y=0;
        }
        //底部超出
        if(y>maxY){
            y=maxY;
        }
        mask.style.top = y + "px";
        mask.style.left = x + "px";

        //比例 = 大图移动的距离/mask移动的距离 = 大图/小图
        var scale = bigImg.offsetWidth / small.offsetWidth;
        bigImg.style.marginLeft = -scale * x +"px";
        bigImg.style.marginTop = -scale * y +"px";

    }
};
//--------------------- JS end ----------------------
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值