javascript實現放大鏡外掛【含進階】

lvxfcjf發表於2021-09-09

放大鏡在網頁中運用廣泛,在淘寶京東上面的商品圖中就用到了,還有在空間上面展示圖片的地方也有用到。現在這種jquery的外掛也有很多,但是也要明白其中原理就可以自己做各種各樣的放大鏡效果了。
現在就來好好分析一下放大鏡的原理和實現的過程:

簡單的實現

成果圖:

圖片描述

影像 1.png

放大鏡的原理

使用兩個圖片,一個是小圖——全部展現在頁面中的,一個是大圖——區域性展示放大的效果。所以由此可以看出突破點,就是網頁中一共有兩張圖,根據他們的移動的距離,可以實現放大鏡的效果。

網頁結構

下面就來寫以下網頁的結構

<!--css樣式--&gt
  <!--html結構--&gt

 <!--放大鏡的整體--&gt
 
     <!--小圖的模組--&gt      
         <!--小圖--&gt          ![](images/small.png)         <!--遮擋層--&gt          
     
     <!--大圖的模組--&gt      
          <!--大圖--&gt          ![](images/big.jpg)     
 

如果上面的骨架搭好了,下面就來分析以下放大鏡的功能步驟:
1.滑鼠移動的時候遮罩層中的框也跟著一起移動
2.在遮罩層移動的時候右邊的大圖也一起移動
3.遮罩層的移動和大圖的移動是相反的,也是按照一定比例進行移動的
4.遮罩層是不能離開小圖的框的

實現步驟

下面上步驟:

第一步 獲取元素

因為這裡面的元素都有可能用到

     //獲取最外面的div
    var box = document.getElementById("box");    //獲取顯示小圖的div
    var small = box.children[0];    //獲取小圖中的遮擋的div
    var mask = small.children[1];    //獲取顯示大圖的div
    var big = box.children[1];    //獲取大div中的大圖
    var imgObj = big.children[0];

第二步  註冊滑鼠進入離開事件

在滑鼠進入的時候,顯示遮擋層和大圖的圖層
在滑鼠離開的時候,隱藏遮擋層和大圖的圖層

      //滑鼠進入事件
      box.onmouseover = function(){
               mask.style.display = "block";
               big.style.display = "block";
      }      //滑鼠離開事件
      box.onmouseout = function(){
               mask.style.display = "none";
               big.style.display = "none";
      }

第三步   註冊滑鼠移動事件(確定遮罩層的定位)

給滑鼠註冊移動事件,在小圖上移動的時候,遮罩層也跟著移動

  • 要拿到可視區域的橫縱座標——clientX,clientY(不考慮相容性)

  • 設定遮罩層的left和top值
    那麼怎麼透過滑鼠的橫縱座標來設定遮罩層的left和top的值呢?
    一張圖來說明白:

圖片描述

mask.png

上圖中的第三步,分析為什麼會出現這樣的問題
因為在滑鼠進入的時候,在滑鼠和小圖的框中加了一個遮罩層,這個遮罩層讓滑鼠和小圖的框進行了分離。所以當滑鼠進行移動的時候,移動到了小圖的框的外面,但是檢測不到滑鼠到底有沒有離開小圖的範圍,所以遮罩層就跟著滑鼠一起可以在可視區域中進行移動。
要想要進行範圍的限定,就類似於一輛車在兩堵牆之間的移動的最大距離一樣。最大的移動距離無非就是小圖框本身的寬度 - 遮罩層本身的寬度

下面上程式碼:

small.onmousemove = function (e) {        var left = e.clientX - mask.offsetWidth / 2;//橫座標
        var top = e.clientY - mask.offsetHeight / 2;//縱座標
        //設定遮擋層的left和top
        var x = left - 100;//margin
        var y = top - 100;//margin

        //為遮擋層設定範圍
        x=xsmall.offsetWidth-mask.offsetWidth?small.offsetWidth-mask.offsetWidth:x;        //如果縱座標大於縱向最大移動距離就設定為縱向最大移動距離
        y=y>small.offsetHeight-mask.offsetHeight?small.offsetHeight-mask.offsetHeight:y;        
        //設定mask的定位
        mask.style.left = x + "px";
        mask.style.top = y + "px";
    };

最後一步  大圖跟著滑鼠移動

  • 如果圖片是有比例的,那麼移動的時候也成比例就可以

  • 如果圖片是不成比例的,那麼就要有一個普遍的演算法
    先來個原理圖:

圖片描述

max.png

上圖說的是寬度,其實高度可以以此類推。
由此可以得出:
**大圖的移動距離 = 遮擋層的移動距離 * 大圖的最大移動距離 / 遮擋層的最大移動距離 **

        //大圖的最大的移動距離
        var imgMaxMove=imgObj.offsetWidth-big.offsetWidth;        //遮擋層的最大的移動距離
        var maskMaxMove=small.offsetWidth-mask.offsetWidth;        //大圖的橫向移動的距離
        var imgMoveLeft=x*imgMaxMove/maskMaxMove;        //大圖的縱向移動的距離
        var imgMoveTop=y*imgMaxMove/maskMaxMove;        //設定大圖的left和top---移動的是margin-left和margin-top

        imgObj.style.marginLeft=-imgMoveLeft+"px";
        imgObj.style.marginTop=-imgMoveTop+"px";

整理一下全部的js程式碼


放大鏡進階

最近要做的這個放大鏡的功能需求是這樣的
擷取螢幕可視區域的圖片然後進行放大。
為了可以看到動態的效果,所以我在上面加了隨機的新增圖示的功能,這樣就可以看到實時的改變。

功能分析

  • 設定按鈕,點選按鈕的時候顯示遮擋層和大圖框

  • 設定新增圖示按鈕,點選在螢幕的隨機位置生成一個圖示

  • 在文字框中輸入文字

  • 擷取可視區域的螢幕並生成圖片

  • 將可視區域的圖片進行放大放入到大圖框中

  • 滑鼠移動的時候大圖框中的也同樣移動

效果圖

圖片描述

tb.png

截圖外掛 html2canvas

這個外掛是讓你整體截圖或者部分截圖的功能,截圖直接在瀏覽器上使用。這個外掛是基於dom操作,但是不是百分百準確的,因為它並不是生成一個圖片,而是基於頁面上的資訊截圖。(說白了就是截下來一部分的資訊然後直接繪製到另一個地方,並不是儲存成了圖片檔案)

注意事項

這個外掛有一定的限制

  • 第一個就是文件不是很全,過於簡單

  • 第二個是其工作原理不是真正生成一個截圖,而是遍歷所有的dom元素構建頁面,所以很多css屬性無法使用

  • 第三個是要求影像同源且沒有代理,這個指令碼不渲染flashappletiframe等內容

可用引數

這些參考API和中文的簡書,寫的很清楚

demo

  • 先引入js檔案

  • 寫html結構

    
             
  • 寫js程式碼


下面還是迴歸正題,開始寫放大鏡的結構:

放大鏡的html結構


    hello world!!    
    
<!--遮罩層--&gt         
<!--相當於小圖--&gt         
<!--跟著滑鼠的層--&gt         
<!--顯示的區域--&gt             
<!--移動的地方--&gt         
    

使用jquery進行程式碼實現

第一步 獲取元素

      //獲取id
      var btn = $('#btn');      var dv = $('#dv');      var box = $('#box');      var mask = $('#mask');      var look = $('#look');      var move = $('#move');      //定義圖片的最大移動距離和跟著滑鼠層的最大移動距離的變數
      var imgMaxMove;      var maskMaxMove;

第二步 註冊按鈕點選事件

  • 點選按鈕的時候顯示遮罩層,同時也顯示出來隨著滑鼠移動的框框,顯示出來圖片顯示的位置。

  • 顯示遮罩層的時候截圖

  • 點選遮罩層的時候遮罩層消失

        //給按鈕註冊點選事件
        btn.on('click',function(){            //截圖功能
            takeScreenshot();            //遮罩層顯示
            dv.css('display','block');
        });        //點選螢幕的時候就消除
        dv.on('click',function(){
            $(this).css('display','none');
        })

第三步 截圖功能

function takeScreenshot() {     //根據body進行截圖
     html2canvas(bd, {          allowTaint: true, //允許跨域
          taintTest: false,  //渲染圖片不用測試圖片
          //渲染圖片
          onrendered: function(canvas) {               //將canvas標籤轉化為img標籤
               canvas.id = 'cv';               var dataUrl = canvas.toDataURL();               var newImg = document.createElement("img");
               newImg.src = dataUrl;               //設定圖片的長和寬
               newImg.width = 4 * bd.width();
               newImg.height = 4* bd.height();               //把圖片的長寬賦值給外面的盒子
               move.width(newImg.width);
               move.height(newImg.height);               //把圖片加到盒子上
               move.append(newImg);
            },
        });
      }

第四步  註冊滑鼠移動事件

  • 不考慮相容的問題,使用clientX

  • 確定不要讓跟著滑鼠的小塊出了螢幕,給它設定範圍

  • 比例這個東西啊,因為之前截圖的時候,長度就進行了擴大,所以比例也不好掌握,後面自己慢慢的調。。。總會差不多的。(給自己留的bug)

//給滑鼠註冊移動事件dv.on('mousemove',function(e){           var left = e.clientX - mask.width() / 2;//橫座標
            var top = e.clientY - mask.height() / 2;//縱座標
            //設定遮擋層的left和top
            var x = left;            var y = top;

            x=xbox.width()-mask.width()?box.width()-mask.width():x;
            y=y>box.height()-mask.height()?box.height()-mask.height():y;            //確定跟著滑鼠動的小塊的定位值
            mask.offset({"left":x,"top":y});            //大圖的最大的移動距離
            imgMaxMove=newImg.width-look.width();            //遮擋層的最大的移動距離
            maskMaxMove=box.width()-mask.width();              
            //大圖的橫向移動的距離
            var imgMoveLeft=x*maskMaxMove/imgMaxMove*9;            //大圖的縱向移動的距離
            var imgMoveTop=y*maskMaxMove/imgMaxMove*9;            // 給大圖設定移動位置
            move.css("marginLeft",-imgMoveLeft);
            move.css("marginTop",-imgMoveTop);
  })

第五步  給螢幕上動態的新增元素

  • 點選新增圖示的時候,在螢幕上隨機的新增一個圖示

  • 可以在文字框中輸入文字資訊

 $('#jb').on('click',function(){            var img = document.createElement('img');
            img.src = 'images/jb.jpg';
            img.width = 100;
            img.height = 100;            var leftRandom = Math.random()*1366; //隨機生成橫座標
            var topRandom = Math.random()*768; //隨機生成縱座標
            img.style.position = 'absolute';
            img.style.left = leftRandom + 'px';
            img.style.top = topRandom + 'px';
            $('#show').append(img);
        })

完整程式碼

css檔案glass.css

*{    margin:0;    padding:0;
}body{    background-image: url('../images/hua.jpg');    background-repeat: no-repeat;    position: absolute;    width: 100%;    height: 100%;
}#dv{    position: absolute;    top: 0;    left: 0;    width: 100%;    height: 100%;    background-color: rgba(0,0,0,0.5);    display: none;
}#btn{    position:absolute;    top: 100px;    left: 100px;    width: 100px;    height:50px;    background-color:rgba(0,0,0,.9);    border-radius: 8px;    line-height: 50px;    text-align: center;    color: #fff;    cursor: pointer;    font-size: 16px;
}#mask{    width: 200px;    height:200px;    position: absolute;    top: 0;    left: 0;    background-color: rgba(255,150,0,.5);    cursor: move;
}#look{    width: 300px;    height:300px;    position: absolute;    bottom: 30px;    right: 30px;    border: 1px solid #f40;    cursor: move;    overflow: hidden;
}#box{    width: 100%;    height:100%;
}#jb{    position:absolute;    left: 100px;    top:200px;    width: 100px;    height: 50px;    background-color: rgba(0,0,0,.9);    border-radius: 8px;    line-height: 50px;    text-align: center;    color: #fff;    cursor: pointer;    font-size: 16px;
}#txt{    position: absolute;    left: 100px;    top: 300px;    width: 100px;    height: 50px;
}

index.html

hello world!!
顯示圖示
放大鏡
<!--遮罩層--&gt     
<!--相當於小圖--&gt     
<!--跟著滑鼠的區域--&gt     
        
<!--移動的地方--&gt     
<!--顯示的區域--&gt

js檔案 glass.js

(function($){
    $.fn.glass = function(){        var mask = $('#mask');        var box = $('#box');        var look = $('#look');        var move = $('#move');        var btn = $('#btn');        var imgMaxMove;        var maskMaxMove;        var _this = $(this);        //點選按鈕
        btn.on('click',function(){
            move.html('');
            takeScreenshot();
            _this.css('display','block');
        });        //點選螢幕的時候就消除
        _this.on('click',function(){
            _this.css('display','none');
        })        //獲取螢幕截圖
        function takeScreenshot() {
            alert('1');
            html2canvas($('#bd'), {                allowTaint: true,                taintTest: false,                onrendered: function(canvas) {
                    canvas.id = 'cv';                    var dataUrl = canvas.toDataURL();                    var newImg = document.createElement("img");
                    newImg.src = dataUrl;
                    newImg.width = 4 * $('#bd').width();
                    newImg.height = 4* $('#bd').height();
                    move.width(newImg.width);
                    move.height(newImg.height);
                    move.append(newImg);


                    _this.on('mousemove',function(e){                        var left = e.clientX - mask.width() / 2;//橫座標
                        var top = e.clientY - mask.height() / 2;//縱座標
                        //console.log(mask.width());
                        //設定遮擋層的left和top
                        var x = left;//margin
                        var y = top;//margin
                        x=xbox.width()-mask.width()?box.width()-mask.width():x;
                        y=y>box.height()-mask.height()?box.height()-mask.height():y;
                        mask.offset({"left":x,"top":y});                        //大圖的最大的移動距離
                        imgMaxMove=newImg.width-look.width();                        console.log(imgMaxMove);                        //遮擋層的最大的移動距離
                        maskMaxMove=box.width()-mask.width();                        console.log(maskMaxMove);                        //大圖的橫向移動的距離
                        var imgMoveLeft=x*maskMaxMove/imgMaxMove*9;                        //大圖的縱向移動的距離
                        var imgMoveTop=y*maskMaxMove/imgMaxMove*9;
                        move.css("marginLeft",-imgMoveLeft);
                        move.css("marginTop",-imgMoveTop);
                    })
                },
            });
        }
    }
})(jQuery);

補充

關於圖片的比例問題
也可以這樣做:
大圖的寬 / 小圖的寬 = 大圖的移動距離 / 小圖的移動距離
這樣就將id = move的標籤進行設定

css:
#move{ position:absolute; top:0; left: 0; }

js:
x = newImg.width / $('#bd').width() * x / 2; y = newImg.width / $('#bd').width() * y / 2; $('#move').css('left',-x); $('#move').css('top',-y);

還是那句話,比例自己調正。。。



作者:頑皮的雪狐七七
連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3486/viewspace-2810995/,如需轉載,請註明出處,否則將追究法律責任。

相關文章