原生JS實現圖片放大鏡效果 - 乾貨分享

準備工做

  1. 須要先了解JS的三個鼠標事件node

    onmouseenter 鼠標進入瀏覽器

    onmouseleave 鼠標移出bash

    onmousemove 鼠標移動佈局

    注意:鼠標移入的時候須要阻止事件的冒泡傳播(ev.stopPropagation),因此不用onmouseover和onmouseoutui

  2. 理解盒子模型spa

    offsetParent:當前盒子的父級參照物code

    offsetLeft / offsetTop:當前盒子距離其父級參照物的偏移量對象

    offsetWidth / offsetHeight:當前元素可視區域的寬高(內容的寬高+padding+border)seo

    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 ----------------------
複製代碼
相關文章
相關標籤/搜索