手牽手,帶你用原生js實現放大鏡特效(一):

前言:

學習該特效須要掌握client、offset系列的知識,不然會有點混亂,能夠看我以前寫的文章精講-offset系列、scroll系列、client系列~,再來學習該文章,這樣會好不少哦~html

實現原理:

首先佈局上,很明顯要準備兩個基本的容器,一個small,一個big,還要準備兩張徹底相同的圖片,可是尺寸不一樣,每一個容器中放入相應大小的圖片,可是小的容器中還要放入一個能夠移動的遮罩。其次就是在實現上,可根據如下步驟來一步一步完成。git

佈局代碼:bash

<div id="box">
    <div id="small">
        <img src="./images/small.png" width="350" alt="">
        <div id="mask"></div>
    </div>
    <div id="big">
        <img src="./images/big.jpg" width="800" alt="">
    </div>
</div>
複製代碼

代碼的樣式最後會貼上,不要着急~佈局

接下來,咱們註冊鼠標進入事件(在box中便可):post

box.onmouseover=function(){
    mask.style.display='block';
    big.style.display='block';
}
複製代碼

註冊鼠標離開事件:學習

box.onmouseout=function(){
    mask.style.display='none';
    big.style.display='none';
}

複製代碼

再接下來,就是重難點了,須要好好理解與消化~網站

第一步: 爲小的容器註冊移動事件,而且讓mask隨着鼠標的移動而移動:spa

small.onmousemove=function(e){
    var x = e.clientX;
    var y = e.clientY;
    mask.style.left = x +'px';
    mask.style.top= y +'px';
}
複製代碼

效果以下:code

問題: 會發現鼠標跟mask並無連在一塊兒,而是在它的左上方,那是什麼緣由致使了這個問題呢?cdn

答案:

在給box的樣式設置中加了這個margin的屬性,因此下面咱們要把這個值減掉,此時鼠標就在mask的左上角啦~

small.onmousemove=function(e){
    var x = e.clientX;
    var y = e.clientY;
    x = x - 50;
    y = y - 50;
    mask.style.left = x +'px';
    mask.style.top= y +'px';
}
複製代碼

第二步: 讓鼠標在mask的中心位置顯示:

要想實現該效果,很明顯,只須要讓mask向左移動自身寬度的1/2,向上移動高度的1/2便可

small.onmousemove=function(e){
    var x = e.clientX-mask.offsetWidth/2;
    var y = e.clientY-mask.offsetHeight/2;
    x = x - 50;
    y = y - 50;
    mask.style.left = x +'px';
    mask.style.top= y +'px';
}
複製代碼

到此,會發現一直存在的一個問題:mask能夠在頁面的任何位置移動,顯然這並不符合咱們的需求,咱們只須要它在small中移動。

第三步: 讓mask只在small所在區域移動,不能夠在這以外的區域移動

若要實現這樣的效果,那必然會有一個移動的最大值,也有一個移動的最小值。當超過這個最大值時,就不能夠繼續移動了,而是保持這個最大值,若沒有超過,就是保留當前這個值,若小於這個最小值,也不能夠繼續移動了,而是保持這個最小值~

爲了你們更直觀的理解,下面我畫圖來爲你們解釋一下:

small.onmousemove=function(e){
    var x = e.clientX-mask.offsetWidth/2;
    var y = e.clientY-mask.offsetHeight/2;
    x = x - 50;
    y = y - 50;
    
    //最小值
    x = x < 0 ? 0 : x;
    y = y <0 ? 0 : y;
    
    //最大值
    x = x > small.offsetWidth-mask.offsetWidth ? small.offsetWidth-mask.offsetWidth : x;
    y = y > small.offsetHeight-mask.offsetHeight ? small.offsetHeight-mask.offsetHeight : y;
    
    mask.style.left = x +'px';
    mask.style.top= y +'px';
}
複製代碼

到此,mask已經不能在small以外的地方移動了,並且鼠標也在mask中心位置~

第四步: mask在small上移動,big上等比例展現相應的部分

若要實現這個效果,則要弄明白一個比例關係式,我先舉個例子:

我之因此舉這個例子,就是由於small與big之間也存在一個對應的比例關係,這也是放大鏡特效實現的最關鍵的地方。

咱們能夠知道mask移動的距離與最大距離,也能夠知道大圖移動的最大距離,只須要求大圖移動的距離便可!

比例: mask的移動距離/大圖的移動距離=mask的最大移動距離/大圖的最大移動距離

因此:大圖的移動距離=mask的移動距離*大圖的最大移動距離/mask的最大移動距離

以橫座標爲例:

  • mask的移動距離 : x
  • 大圖的最大移動距離 : big.children[0].offsetWidth - big.offsetWidth
  • mask的最大移動距離 : small.offsetWidth - mask.offsetWidth

因此大圖移動的距離就能夠算出來了~

以上,第一點mask的移動距離 和第三點mask的最大移動距離上面都解釋過了,可是這個大圖的最大移動距離可能有些人還不能理解,那我這裏來解釋一下,大圖的容器box的寬度沒有大圖的寬度大,這樣就很好理解了吧~

small.onmousemove=function(e){
    var x = e.clientX-mask.offsetWidth/2;
    var y = e.clientY-mask.offsetHeight/2;
    x = x - 50;
    y = y - 50;
    
    //最小值
    x = x < 0 ? 0 : x;
    y = y <0 ? 0 : y;
    
    //最大值
    x = x > small.offsetWidth-mask.offsetWidth ? small.offsetWidth-mask.offsetWidth : x;
    y = y > small.offsetHeight-mask.offsetHeight ? small.offsetHeight-mask.offsetHeight : y;
    
    mask.style.left = x +'px';
    mask.style.top= y +'px';
    
    var maskMoveMaxX = small.offsetWidth - mask.offsetWidth;
    var maskMoveMaxY = small.offsetHeight - mask.offsetHeight;
    var bigMoveMaxX = big.children[0].offsetWidth - big.offsetWidth;
    var bigMoveMaxY = big.children[0].offsetHeight - big.offsetHeight;

    var bigImgX = x * bigMoveMaxX / maskMoveMaxX;
    var bigImgY = y * bigMoveMaxY / maskMoveMaxY;
}
複製代碼

第五步:將大圖移動的距離賦值給負margin:

這裏你們可能會有疑惑, (1)爲何是負margin?

你們能夠進一些購物網站看一下放大鏡的效果,當mask在小圖上向右移動時,其實大圖是向左移動的,則方向是反的,因此固然是負margin咯~

(2)那爲何要將計算的結果賦值給margin,而不是left,或者top呢?

你們能夠先試一下,試一下就知道爲何了。由於咱們只是給big設置了定位,它脫離了文檔流,可是裏面的內容並無脫離文檔流,因此left與top的值不起做用,因此咱們用margin.

small.onmousemove=function(e){
    var x = e.clientX-mask.offsetWidth/2;
    var y = e.clientY-mask.offsetHeight/2;
    x = x - 50;
    y = y - 50;
    
    //最小值
    x = x < 0 ? 0 : x;
    y = y <0 ? 0 : y;
    
    //最大值
    x = x > small.offsetWidth-mask.offsetWidth ? small.offsetWidth-mask.offsetWidth : x;
    y = y > small.offsetHeight-mask.offsetHeight ? small.offsetHeight-mask.offsetHeight : y;
    
    mask.style.left = x +'px';
    mask.style.top= y +'px';
    
    var maskMoveMaxX = small.offsetWidth - mask.offsetWidth;
    var maskMoveMaxY = small.offsetHeight - mask.offsetHeight;
    var bigMoveMaxX = big.children[0].offsetWidth - big.offsetWidth;
    var bigMoveMaxY = big.children[0].offsetHeight - big.offsetHeight;

    var bigImgX = x * bigMoveMaxX / maskMoveMaxX;
    var bigImgY = y * bigMoveMaxY / maskMoveMaxY;
    
    big.children[0].style.marginLeft = -bigImgX +'px';
    big.children[0].style.marginTop = -bigImgY +'px';
}
複製代碼

好啦,到這裏全部的邏輯代碼都結束啦,但願對你有所幫助~

那樣式代碼我這裏就不貼了,你們能夠去個人碼雲上下載下來碼雲

相關文章
相關標籤/搜索