記錄--前端如何截圖

林恒發表於2024-06-19

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

前端常用的截圖儲存的方法

  1. 利用 Blob 物件和 URL.createObjectURL:可以將截圖資料轉換為 Blob 物件,然後使用 URL.createObjectURL 方法生成一個臨時的 URL,將這個 URL 賦值給 <a> 標籤的 href 屬性,再設定 download 屬性為所需的檔名,這樣使用者點選連結時會自動下載圖片檔案。
  2. 利用 canvas 的 toDataURL 方法:可以將截圖繪製到一個 canvas 元素上,然後使用 canvas 的 toDataURL 方法將 canvas 中的內容轉換為 data URL,再建立一個臨時的 <a> 標籤,將 data URL 賦值給 href 屬性,設定 download 屬性為所需的檔名,從而實現下載功能。

利用 Blob 物件和 URL.createObjectURL

  1. **生成 Blob 物件:**首先,將截圖資料轉換為 Blob 物件。Blob 物件是用於表示二進位制資料的物件,可以透過將資料傳遞給 Blob 建構函式來建立。在這個場景中,截圖資料通常是 base64 編碼的字串,需要將其解碼為二進位制資料,然後再轉換為 Blob 物件。
  2. **建立臨時 URL:**使用 URL.createObjectURL 方法生成一個臨時的 URL。這個 URL 指向 Blob 物件的內容。生成的 URL 是唯一的,且在頁面關閉時會被自動釋放,因此稱為臨時 URL。
  3. **建立下載連結:**將生成的臨時 URL 賦值給 <a> 標籤的 href 屬性。同時,設定 download 屬性為所需的檔名,這樣使用者點選連結時會自動下載圖片檔案。

利用 canvas 的 toDataURL 方法

  1. **繪製到 canvas:**將截圖資料繪製到一個 canvas 元素上。首先,建立一個新的 canvas 元素,並設定其大小與所需的截圖大小相同。然後,使用 JavaScript 將截圖資料繪製到這個 canvas 上。
  2. **轉換為 data URL:**使用 canvas 的 toDataURL 方法將 canvas 中的內容轉換為 data URL。這個方法可以將 canvas 中的影像資料轉換為 base64 編碼的字串,表示為一個 URL。
  3. **建立下載連結:**將生成的 data URL 賦值給 <a> 標籤的 href 屬性,同時設定 download 屬性為所需的檔名。使用者點選連結時會自動下載圖片檔案。

微信小程式

如果是微信小程式中,因為不是 html,處理會有差別。在微信小程式中,要實現截圖功能,可以使用小程式官方提供的 wx.canvasToTempFilePath 介面。這個介面可以將 Canvas 中的內容轉換為臨時檔案路徑,從而實現截圖功能。

具體步驟如下:

  1. 建立一個 <canvas> 元素,並將需要截圖的內容繪製到這個 Canvas 上。
  2. 呼叫 wx.canvasToTempFilePath 介面將 Canvas 中的內容轉換為臨時檔案路徑。
  3. 獲取到臨時檔案路徑後,可以進行後續的操作,例如儲存到相簿、上傳到伺服器等。

Node.js

上面看到現在由於有各種端,不一定支援 html 或者 canvas,並且各個裝置、端上不能保證完全一致,所以可以在後端直接生成圖片,前端根據連結下載截圖。

在 Node.js 中實現截圖和截長圖的功能可以使用 Puppeteer 庫。Puppeteer 是一個由 Google 開發的 Node.js 庫,它提供了一個高階 API 來透過 Chromium 或者 Chrome 控制瀏覽器的行為。利用 Puppeteer,可以模擬瀏覽器的行為,並實現在瀏覽器中進行截圖和截長圖的功能。

在使用 Puppeteer 實現截圖和截長圖的過程中,需要注意以下幾點:

  1. **安裝 Puppeteer:**首先需要安裝 Puppeteer 庫,可以透過 npm 進行安裝:npm install puppeteer
  2. **使用 Puppeteer 截圖:**使用 Puppeteer 提供的 API,可以直接在瀏覽器中開啟網頁,並將網頁內容截圖儲存為圖片。
  3. **實現截長圖:**要實現擷取長圖的功能,可以模擬頁面的滾動,並多次擷取不同部分的內容,然後將擷取到的內容拼接成一張長圖。
  4. **相容瀏覽器和微信小程式:**Puppeteer 庫是針對 Node.js 環境開發的,不能直接在瀏覽器或者微信小程式中使用。如果要在瀏覽器或者微信小程式中實現截圖和截長圖的功能,可以考慮使用前面提到的瀏覽器中截圖的方法或者小程式中截圖的方法。

Puppeteer

在 Puppeteer 中實現擷取長圖的功能相對複雜,因為 Puppeteer 預設只能擷取當前視口(Viewport)的內容,無法直接擷取整個頁面的內容。但可以透過模擬頁面的滾動,並多次擷取不同部分的內容,然後將擷取到的內容拼接成一張長圖來實現。

以下是一種實現擷取長圖的方法:

  1. **設定視口大小:**首先,需要設定頁面的視口大小,以確保可以顯示所有要擷取的內容。可以使用 page.setViewport() 方法設定頁面的寬度和高度。

  2. **模擬頁面滾動:**透過執行 JavaScript 程式碼來模擬頁面的滾動,以便逐步擷取頁面的不同部分。可以使用 page.evaluate() 方法來執行 JavaScript 程式碼。

  3. **多次擷取內容:**在模擬滾動的過程中,每次滾動一定的距離後,使用 page.screenshot() 方法擷取當前視口的內容,並儲存為圖片。

  4. **拼接截圖:**將擷取到的多張圖片拼接成一張長圖。可以使用第三方庫來實現圖片拼接的功能,比如 merge-img

下面是一個簡單的示例程式碼,演示如何在 Puppeteer 中實現擷取長圖的功能:

const puppeteer = require('puppeteer');
const mergeImg = require('merge-img');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.setViewport({ width: 1200, height: 800 }); // 設定頁面視口大小

  await page.goto('https://example.com'); // 開啟頁面

  const chunks = []; // 儲存擷取的圖片資料

  const scrollHeight = await page.evaluate(() => {
    // 模擬頁面滾動,返回頁面的滾動高度
    const distance = 800; // 每次滾動的距離
    let totalHeight = 0;
    const timer = setInterval(() => {
      window.scrollBy(0, distance);
      totalHeight += distance;
      if (totalHeight >= document.body.scrollHeight) {
        clearInterval(timer);
      }
    }, 100);
    return document.body.scrollHeight;
  });

  for (let i = 0; i < scrollHeight; i += 800) {
    // 每次滾動800px,擷取當前視口的內容並儲存為圖片
    const screenshot = await page.screenshot({ clip: { x: 0, y: i, width: 1200, height: 800 } });
    chunks.push(screenshot);
  }

  await browser.close();

  // 拼接擷取的圖片
  const mergedImg = await mergeImg(chunks, { direction: true });

  // 儲存拼接後的長圖
  await mergedImg.write('long_screenshot.png');
})();

在這個示例中,我們首先設定了頁面的視口大小為 1200x800,然後開啟了一個頁面,並模擬了頁面的滾動,每次滾動800px。在滾動過程中,透過多次呼叫 page.screenshot() 方法擷取當前視口的內容,並儲存為圖片。最後,使用 merge-img 庫將所有擷取到的圖片拼接成一張長圖,並儲存到本地。

需要注意的是,這只是一個簡單的示例程式碼,實際場景中可能需要根據頁面的具體情況進行調整和最佳化。

本文轉載於:https://juejin.cn/post/7360320083221823525

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

記錄--前端如何截圖

相關文章