實現放大鏡效果

1、概念明確

首先知道幾個頁面位置信息的apicss

image.png

補充:html

image.png

2、分割版

這一版主要是在小圖右側放一個大圖,經過大圖移動位置以及利用層級關係,顯示大圖的部分區域,展示放大的效果. 計算公式: 大圖的left = -(左側圖片內滑塊left / (左側圖片寬度 - 滑塊寬度)) * (右側大圖寬度 - 右側大圖展示區域寬度)api

HTML代碼

頁面結構很簡單,總的來講就是須要兩張圖片,一張小圖片和一張如出一轍的大圖片,主要複雜的是js中的計算部分:瀏覽器

<div id="demo">
    <!-- 左邊的小圖 -->
    <div id="small-box">
        <div id="mark"></div>
        <!-- 放大鏡 -->
        <div id="float-box"></div>
        <img src="small.jpg"/>
    </div>
    <!-- 顯示的大圖 -->
    <div id="big-box">
        <img src="big.jpg"/>
    </div>
</div>
複製代碼

CSS代碼

<style>
    * {
        margin: 0;
        padding: 0
    }
    #demo {
        display: block;
        width: 400px;
        height: 255px;
        margin: 50px;
        position: relative;
        border: 1px solid #ccc;
    }
    #small-box {
        position: relative;
        z-index: 1;
    }
    #float-box {
        display: none;
        width: 160px;
        height: 120px;
        position: absolute;
        background: #ffffcc;
        border: 1px solid #ccc;
        filter: alpha(opacity=50);
        opacity: 0.5;
    }
    #mark {
        position: absolute;
        display: block;
        width: 400px;
        height: 255px;
        background-color: #fff;
        filter: alpha(opacity=0);
        opacity: 0;
        z-index: 10;
    }
    #big-box {
        display: none;
        position: absolute;
        top: 0;
        left: 460px;
        width: 400px;
        height: 300px;
        overflow: hidden;
        border: 1px solid #ccc;
        z-index: 1;;
    }
    #big-box img {
        position: absolute;
        z-index: 5
    }
</style>
複製代碼

此時咱們頁面上就只有一張小圖片markdown

JavaScript代碼

<script>
    //頁面加載完畢後執行
    window.onload = function () {
        var objDemo = document.getElementById("demo");
        var objSmallBox = document.getElementById("small-box");
        var objMark = document.getElementById("mark");
        var objFloatBox = document.getElementById("float-box");
        var objBigBox = document.getElementById("big-box");
        var objBigBoxImage = objBigBox.getElementsByTagName("img")[0];
        //鼠標一如事件
        objMark.onmouseover = function () {
            objFloatBox.style.display = "block"
            objBigBox.style.display = "block"
        }
        //鼠標移出事件
        objMark.onmouseout = function () {
            objFloatBox.style.display = "none"
            objBigBox.style.display = "none"
        }
        //鼠標移動事件
        objMark.onmousemove = function (ev) {
            var _event = ev || window.event;  //兼容多個瀏覽器的event參數模式
            var left = _event.clientX - objDemo.offsetLeft - objSmallBox.offsetLeft - objFloatBox.offsetWidth / 2;
            var top = _event.clientY - objDemo.offsetTop - objSmallBox.offsetTop - objFloatBox.offsetHeight / 2;
            if (left < 0) {
                left = 0;
            } else if (left > (objMark.offsetWidth - objFloatBox.offsetWidth)) {
                left = objMark.offsetWidth - objFloatBox.offsetWidth;
            }
            if (top < 0) {
                top = 0;
            } else if (top > (objMark.offsetHeight - objFloatBox.offsetHeight)) {
                top = objMark.offsetHeight - objFloatBox.offsetHeight;
            }
            objFloatBox.style.left = left + "px"; 
            objFloatBox.style.top = top + "px";
            var percentX = left / (objMark.offsetWidth - objFloatBox.offsetWidth);
            var percentY = top / (objMark.offsetHeight - objFloatBox.offsetHeight);
            objBigBoxImage.style.left = -percentX * (objBigBoxImage.offsetWidth - objBigBox.offsetWidth) + "px";
            objBigBoxImage.style.top = -percentY * (objBigBoxImage.offsetHeight - objBigBox.offsetHeight) + "px";
                    }
    }
</script>
複製代碼

3、糅合版

image.png

所謂優雅版就是把鼠標變成放大鏡,這樣就會有比較真實的用放大鏡看東西的效果函數

大體實現思路以下:url

1)原圖部分添加mouseover監聽函數,在鼠標移入原圖後,獲取鼠標距離原圖的top和left的位置spa

2)在鼠標放大鏡區域,設置區域背景爲放大後的圖片,設置爲backgroundcode

3)反向計算放大後圖片應該移動的距離,設置background-positionorm

HTML代碼

html部分代碼很是簡單,就是一個原圖背景圖,還有就是兩個不顯示的img元素,這兩個不顯示的元素,主要是用來獲取圖片的寬高

<div id="background" className={styles.originImage} style={{backgroundImage: `url(${url})`}}>
      <img src={url} />
      <img id="bigger" src={url} />
      <div id="manifier" className={styles.biggerImage} style={{backgroundImage: `url(${url})`}} />
</div>
複製代碼

JavaScript代碼

js代碼主要分爲兩部分

1)監聽鼠標在原圖上的移動

const listenBackMousemove = (e: globalThis.MouseEvent) => {
    if (!manifier || !background) return
    let left = e.offsetX - manifier.offsetWidth / 2,
      top = e.offsetY - manifier.offsetHeight / 2
    if (left < 0) left = 0
    else if (left > background.offsetWidth - manifier.offsetWidth)
      left = background.offsetWidth - manifier.offsetWidth
    if (top < 0) top = 0
    else if (top > background.offsetHeight - manifier.offsetHeight)
      top = background.offsetHeight - manifier.offsetHeight
    manifier.style.visibility = 'visible'
    manifier.style.left = left + 'px'
    manifier.style.top = top + 'px'
    imgMove(left, top)
}
複製代碼

2)根據鼠標在原圖上移動的距離,反向計算放大後的圖片應該移動的距離

const imgMove = (left: number, top: number) => {
    if (!bigger || !background || !manifier) return
    const imgWidth = bigger.offsetWidth
    const imgHeight = bigger.offsetHeight
    const backHeight = background.offsetHeight
    const backWidth = background.offsetWidth
    const manHeight = manifier.offsetHeight
    const manWidth = manifier.offsetWidth
    const rateX = left / (backWidth - manWidth)
    const rateY = top / (backHeight - manHeight)
    let imgLeft = -(rateX * (imgWidth - manWidth)),
      imgTop = -(rateY * (imgHeight - manHeight))
    if (imgLeft > 0) imgLeft = 0
    else if (imgLeft < -(imgWidth - manWidth)) imgLeft = -(imgWidth - manWidth)
    if (imgTop > 0) imgTop = 0
    else if (imgTop < -(imgHeight - manHeight)) imgTop = -(imgHeight - manHeight)
    manifier.style.backgroundPosition = `${imgLeft}px ${imgTop}px`
}
複製代碼

CSS部分代碼

.originImage {
  background-position: center center;
  background-size: contain;
  background-repeat: no-repeat;
  position: relative;
  & > img:nth-child(1) {
    width: 100%;
    height: auto;
    visibility: hidden;
  }

  & > img:nth-child(2) {
    width: auto;
    height: auto;
    position: absolute;
    left: -9999px;
    top: 0;
  }

  .biggerImage {
    position: absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #ededed;
    border-radius: 10px;
    cursor: none;
    pointer-events: none;
  }
}
複製代碼

css部分有一個點須要注意,須要將鼠標放大鏡的鼠標屬性設置爲none,即穿透效果,這樣在背景原圖上的移動就不會受影響。不然可能會走進鼠標放大鏡區域的mouseover事件

相關文章
相關標籤/搜索