欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用JS實現任意位置縮放圖片功能

 更新時間:2024年04月16日 08:57:43   作者:zyronon  
本文將用一個簡單的例子詳細講解如何用原生JS一步步實現完整的任意位置縮放圖片功能,無任何第三方依賴,指針事件 進行多端統(tǒng)一的事件監(jiān)聽,干貨滿滿,需要的朋友可以參考下

前言

本文將用一個簡單的例子詳細講解如何用原生JS一步步實現完整的任意位置縮放圖片功能,無任何第三方依賴,指針事件 進行多端統(tǒng)一的事件監(jiān)聽,干貨滿滿。

完整代碼

HTML:

<div class="wrapper">
  <img id="image"
         alt=""
         src="https://images.pexels.com/photos/459203/pexels-photo-459203.jpeg"/>
</div>

CSS:

html, body {
    margin: 0;
    padding: 0;
    overflow: hidden;
}

.wrapper {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #000;
}

img { 
  max-height: 80vh;
  touch-action: none;
}

JavaScript:

window.onload = () => {

  // 獲取dom
  const wrapper = document.querySelector(".wrapper");
  const image = document.getElementById("image");
  // 全局變量
  let rect,
    x = 0,
    y = 0,
    scale = 1,
    minScale = 0.2,
    maxScale = 16,
    isPointerdown = false, // 按下標識
    lastPointermove = { x: 0, y: 0 }; // 用于計算diff

    
  rect = image.getBoundingClientRect()
  // 拖拽查看
  drag();
  // 滾輪縮放
  wheelZoom();

  // 拖拽查看
  function drag() {
    // 綁定 pointerdown
    image.addEventListener("pointerdown", function (e) {
      isPointerdown = true;
      lastPointermove = { x: e.clientX, y: e.clientY };
    });
    // 綁定 pointermove
    image.addEventListener("pointermove", function (e) {
      if (isPointerdown) {
        const current = { x: e.clientX, y: e.clientY };
        x += current.x - lastPointermove.x;
        y += current.y - lastPointermove.y;
        lastPointermove = current;
        image.style.transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ")";
      }
      e.preventDefault();
    });
    // 綁定 pointerup
    image.addEventListener("pointerup", function (e) {
      if (isPointerdown) {
        isPointerdown = false;
      }
    });
  }

  // 滾輪縮放
  function wheelZoom() {
    wrapper.addEventListener("wheel", function (e) {
      let d = e.deltaY < 0 ? 0.1 : -0.1;
      let ratio = 1 + d;

      let temp_scale = scale * ratio;
      if (temp_scale > maxScale) return
      if (temp_scale < minScale) return
      scale = temp_scale

      if (e.target.tagName === "IMG") {
        const max = {
          x: (d * rect.width) / 2,
          y: (d * rect.height) / 2,
        };
        const mouseOffset = {
          x: e.clientX - rect.x,
          y: e.clientY - rect.y
        }
        // 計算每次的偏移量
        x -= d * (mouseOffset.x - x) - max.x;
        y -= d * (mouseOffset.y - y) - max.y;
        image.style.transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ")";
      }
      e.preventDefault();
    });
  }
}

實現原理

實現圖片放大的關鍵點在于 CSS3 中的 transform 變換,該屬性應用于元素在2D或3D上的旋轉,縮放,移動,傾斜等等變換,通過設置 translate(x,y) 即可偏移元素位置,設置 scale 即可縮放元素,當然你也可以只設置 matrix 來完成上述所有操作,這涉及到矩陣變換的知識,本文使用的均是CSS提供的語法糖進行變換操作。

PC上的點擊、移動,H5的手勢操作,都離不開DOM事件監(jiān)聽。例如鼠標移動事件對應 mousemove ,移動端因為沒有鼠標則對應 touchmove,而本文將介紹如何僅通過指針事件來進行多端統(tǒng)一 的事件監(jiān)聽。在監(jiān)聽事件中我們可以通過 event 對象獲取各種屬性,例如常用的 offsetX、offsetY 相對偏移量,clientX、clientY 距離窗口的橫坐標和縱坐標等。

理解transform-origin值

官方文檔解釋為:**transform-origin**CSS 屬性讓你更改一個元素變形的原點。 https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin

我們可以簡單的理解為圖片縮放起點,這個值默認為圖片的正中心,所以我們進行放大或縮小都是依圖片中心來縮放。

css縮放圖片有兩種方法

一、修改transform-origin值進行縮放

優(yōu)點:簡單快捷,容易理解

缺點:頻繁修改transform-origin值會抖動,需要計算修正量

將鼠標當前的偏移量offsetX、offsetY 的值改變 transform-origin 來動態(tài)設置縮放的原點,再進行縮放,那么最終效果就是依照最新的transform-origin值來進行縮放。

比如修改transform-origin值為90% 90%。再設置放大倍數scale為1.1。效果就是下圖的樣子

二、不修改transform-origin值,設置偏移量translate(x,y)進行縮放

我們利用滾輪事件監(jiān)聽并改變 scale 值。重點是利用 deltaY 值的正負來判斷滾輪是朝上還是朝下:

let scale = 1;
image.addEventListener("wheel", function (e) {
  //d值永遠是正的0.1或者負的0.1,代表每次縮放的倍數
  let d = e.deltaY < 0 ? 0.1 : -0.1;
  scale = scale * (1 + d);
...
});

如上圖,怎么樣從左圖變成右圖呢?由于我們未修改transform-origin,所以縮放始終都以圖片中心 為原點進行縮放,這顯然不符合我們的操作習慣,我們需要的是以鼠標點為中心對圖片進行縮放。

可以清晰的看到,我們先將圖片放大0.1倍,再設置偏移量translate(x,y)就可以實現任意位置縮放

需要計算的translate(x,y)值,實際上就是放大后的圖片中心點與原始圖片中心點的差值

每次可偏移translate(x,y)最大值 = 長寬 * 放大倍數 / 2

例如:長400,寬為800的圖片。放大0.1倍之后,圖片的長為440,寬為880。如果是在中心點放大,那么不需要移動圖片,xy等于0。如果在左上角放大,那么圖片整體向右下角偏移 x = (440 - 400) / 2 = 20,y = (880 - 800) / 2 = 40.

let d = e.deltaY < 0 ? 0.1 : -0.1;
const max = {
  x: (d * rect.width) / 2,
  y: (d * rect.height) / 2,
};

鼠標點的座標減去圖片的在頁面中的位置可以得到鼠標在圖片中的位置

rect = image.getBoundingClientRect()
const mouseOffset = {
  x: e.clientX - rect.x,
  y: e.clientY - rect.y
}

最后用mouseOffset減去已偏移的xy,再剩以放大倍數d,再減去max,就是當前的translate(x,y)

  • 因為mouseOffset的值,基本可以看作為一個常量,如果鼠標不移動位置,那么mouseOffset的值不會變,所以需要減去已偏移的xy,才能累計偏移量
  • 再剩以放大倍數,得到的值,還不能用于偏移
  • 第二步得到的這個值已經超過我們的最大偏移值max,所以需要減去max,最終就是當前的偏移量
// 計算每次的偏移量
x -= d * (mouseOffset.x - x) - max.x;
y -= d * (mouseOffset.y - y) - max.y;
image.style.transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ")";

移動圖片

移動圖片的實現是比較簡單的,在每次指針按下時我們記錄 clientXclientY 為初始值,移動時計算當前的值與初始點位的差值加到 translate 偏移量中即可另外當抬起動作結束時,會觸發(fā) click 事件,所以注意加入全局變量標記以及定時器進行一些判斷處理。

image.addEventListener("pointerdown", function (e) {
  isPointerdown = true;
  lastPointermove = {x: e.clientX, y: e.clientY};
}); 
image.addEventListener("pointermove", function (e) {
  if (isPointerdown) {
    const current = {x: e.clientX, y: e.clientY};
    x += current.x - lastPointermove.x;
    y += current.y - lastPointermove.y;
    lastPointermove = current;
    image.style.transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ")";
  }
  e.preventDefault();
}); 
image.addEventListener("pointerup", function (e) {
  isPointerdown = false;
});

結束

到此這篇關于使用JS實現任意位置縮放圖片功能的文章就介紹到這了,更多相關JS任意位置縮放圖片內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論