DEV Community

Cover image for 簡單的網頁截圖功能 - DOM to Image
Let's Write
Let's Write

Posted on • Edited on • Originally published at letswrite.tw

簡單的網頁截圖功能 - DOM to Image

本篇要解決的問題

去年九月時,August 有寫了一篇〈簡單的網頁截圖功能 – html2canvas、Canvas2image〉,當時寫完後,以為這就是前端在網頁截圖這塊的終極套件(咦?)。結果最近工作上真的要使用這套截圖、下載的功能時,才發現真實的情形下,因為網頁會比 Demo 中的複雜,所以存下來的圖,圖片裡的網頁有些部份是跑版的!

傻眼,還得另外調一版 CSS 給截圖狀態下的網頁,多耗了一點時間。

最近又有另一個案子要使用截圖並下載的功能,發現一樣會有跑版的情形,August 眉頭一皺,覺得案情並不單純,所以就問了 ChatGPT 看有沒有替代的工具,對話如下圖:

ChatGPT 提供網頁截圖的套件

立刻試了一下裡面提到的 dom-to-image,發現不會跑版耶,而且下載下來的圖片,檔案大小少很多。

但中間過程中還是有踩到坑,就決定為這個套件再寫一篇截圖的功能,讓大家要使用時可以拿來當速成避坑指南。

本篇最後有一個彩蛋,是關於最近被生成式 AI 給影響的部份,可以看到最後喔。

本篇最後完成的 Demo:

https://letswritetw.github.io/letswrite-dom-to-image/


安裝 DOM to Image

DOM to Image:https://github.com/tsayen/dom-to-image

安裝方式就跟一般要使用 JavaScript 的套件一樣,可以直接 CDN 引用或是用 npm package。

CDN



<script src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"></script>


Enter fullscreen mode Exit fullscreen mode

npm package

先安裝 package:



$ npm install dom-to-image
或
$ yarn add dom-to-image


Enter fullscreen mode Exit fullscreen mode

JS 中 import:



import domtoimage from 'dom-to-image';


Enter fullscreen mode Exit fullscreen mode

使用 Dom to Image

DOM to Image 可以指定存成 JPEG、PNG、SVG。

SVG 因為 August 沒實際上用到,這邊就不會使用。

以下示範存成 PNG 的圖檔。



// 抓取指定的 div,產生 base64 格式圖片
// 之所以重複二次,下一段的注意事項會解釋
const el = document.getElementById('xxx');
const config = {
    quality: 1,
    style: {
        "filter": "grayscale(100%)"
    }
};

const dataUriTemp = await domtoimage.toPng(el, captureConfig).then(dataUrl => dataUrl);
const dataUri = await domtoimage.toPng(el, captureConfig).then(dataUrl => dataUrl);

// 下載圖片
const link = document.createElement('a');
const filename = 'Demo.png';
link.download = filename;
link.href = dataUri;
link.click();


Enter fullscreen mode Exit fullscreen mode

如果想存成 JPEG,就是把 toPng 改成 toJpeg,然後檔案的部份副檔名也要記得改成 *.jpeg

程式碼中的 config 是可傳入的參數,這邊示範的是改 qualitystyle

因為 style 寫了 filter: grayscale(100%),所以下載下來的圖片都會變成灰階。

如果是活動性質的頁面,截圖前加上 style 會是很有趣的作法。

可用的參數如下:

  • filter:可以濾掉指定的 tag。官方文件是用在濾掉 SVG 的 tag。
  • bgcolor:指定背景色。
  • width、height:指定寬、高。
  • style:可以加上額外的 style。
  • quality:圖片的品質,數值是 0 - 1,1 為最高,預設是 1。
  • cacheBust:要不要清除緩存,true 是要、false 是否,預設是 false。
  • imagePlaceholder:如果抓不到 div 的圖片,要給什麼墊檔圖,看文件是要填 Base64。

注意事項

以下是 August 踩了一上午的坑後,終於發現在手機操作時有 2 個要注意的地方,不注意的話會讓 Dom-to-Image 產生的圖檔,div 中的圖片變一片空白:

  • 圖片有 position: relative
  • 執行 domtoimage.toJpeg(targetId, [config]) 時,第一次圖片的地方會是空白,但第二次以後就會正常,所以……雖然很蠢,但為了維持手機世界的和平,請執行二次,這就是為什麼範例程式碼會先寫一次 dataUriTemp,接著又寫了一次 dataUri

另外,還有一種情形會讓下載的圖片不完整,就是抓取的 div 本身有寫 max-width: xxx; margin: 0 auto;,寫了 max-width,會讓 DOM to Image 在抓圖時寫上限定的寬,但因為抓圖不會跟著置中,就變成抓下來的位置會從最左邊開始,造成抓下來的圖右邊會被裁切掉。


本篇 Demo 及原始碼

本篇的程式碼有放上 GitHub 上,也用 GitHub Pages 產生了 Demo,請自行取用,但希望在取用前能分享本篇,或在 GitHub 上點個星星,你的一個小小動作對本站都是大大的鼓勵。

原始碼:https://github.com/letswritetw/letswrite-dom-to-image

Demo:https://letswritetw.github.io/letswrite-dom-to-image/


Notion AI 生成的文章

其實在開始要寫這篇時,August 就被生成式 AI 驚呆了。

August 前幾天才通過 Notion 加上 AI 的功能申請,所以當今天打開 Notion,才打完本篇的標題後,就跳出一個「Ask AI to write」的選項,好奇了按了一下……AI 就把本篇幾百字關於 DOM to Image 的介紹及應用文章寫完了,雖然給的是英文。

好啊,都給 AI 寫就好啊~~~

其實在開始用了 ChatGPT 後,就在想是不是還要繼續堅持寫學習的筆記文?

因為未來大家會愈來愈來常先問 AI,問不到才 Google。

那,即便堅持寫,也是寫給 AI 拿去學習用的吧?來網站的人,真實的人類會愈來愈少。

這樣,還有經營的必要嗎?現在除了「之後面試時可以當作品集」的理由,想不到其它繼續寫下去的理由了。

Anyway,以下是 Notion AI 所編寫的文章,有經過 August 修改,把文字從英文轉成中文,並調整了詞句。

大家可以對比一下上面幾段出自 August 的真人文字,跟下面幾段 AI 所生成的文字,未來 August 撰文,為了省時間跟心力,會陸續使用 AI 提供的文字了。


DOM to Image 是一個非常有用的工具,用於建立網頁的螢幕截圖。它允許用戶通過點擊一個按鈕快速輕鬆地抓取網頁的快照然後保存,可以共享結果給朋友或同事。

本篇筆記文將提供一個使用 DOM to Image 建立一個簡單的網頁截圖功能的簡單教學。

第一步是在 HTML 頁面中引用 DOM to Image 的 JS。這可以在 HTML 引用 CDN 來快速輕鬆完成:

<script src="https://unpkg.com/dom-to-image@2.6.0/dist/dom-to-image.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

引用了 CDN 後,還需要建立一個函數,這個函數可以讓我們抓取螢幕截圖。

此函數接受 HTML 元素作為參數,並返回一個解析為圖像的 Promise。

以下是使用 {% raw %}domtoimage.toPng() 的方法完成的:

function captureScreenshot(element) {
  return new Promise((resolve, reject) => {
    domtoimage.toPng(element)
      .then((dataUrl) => {
        resolve(dataUrl);
      })
      .catch((error) => {
        reject(error);
      });
  });
}

Enter fullscreen mode Exit fullscreen mode

建立函數後,執行函數便可從 HTML 中輕鬆獲取螢幕截圖:

captureScreenshot(document.getElementById('element-id'));
Enter fullscreen mode Exit fullscreen mode

這是這樣!只需幾行代碼,您現在就可以使用強大的 DOM to Image 建立一個簡單的網頁截圖功能。

當我們需要快速抓取網頁的螢幕截圖時,此明件可以節省時間和麻煩,對於任何使用網頁的人來說,它都是一個不可多得的工具。

Top comments (0)