dom-to-image 解決 html2canvas 圖片不支持css filter屬性


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

這是什么

dom-映像是一個庫,可以將任意 DOM 節點轉換為以 JavaScript 編寫的矢量 (SVG) 或柵格 (PNG 或 JPEG) 圖像。它基於保羅·巴考斯的domvas,已經完全重寫,一些錯誤固定和一些新功能(如網絡字體和圖像支持)添加。

安裝

Npm

npm install dom-to-image

然后加載

/* in ES 6 */
import domtoimage from 'dom-to-image'; /* in ES 5 */ var domtoimage = require('dom-to-image');

鮑爾

bower install dom-to-image

在頁面中包括 或 ,它將使變量在全局范圍內可用。src/dom-to-image.jsdist/dom-to-image.min.jsdomtoimage

<script src="path/to/dom-to-image.min.js" /> <script> domtoimage.toPng(node) //... </script>

使用

所有頂級函數都接受 DOM 節點和呈現選項,並返回承諾,這些承諾通過相應的數據 URL 實現。
獲取 PNG 映像基礎 64 編碼的數據 URL 並馬上顯示:

var node = document.getElementById('my-node'); domtoimage.toPng(node) .then(function (dataUrl) { var img = new Image(); img.src = dataUrl; document.body.appendChild(img); }) .catch(function (error) { console.error('oops, something went wrong!', error); });

獲取 PNG 圖像 Blob 並下載它(例如,使用 FileSaver):

domtoimage.toBlob(document.getElementById('my-node')) .then(function (blob) { window.saveAs(blob, 'my-node.png'); });

保存並下載壓縮的 JPEG 映像:

domtoimage.toJpeg(document.getElementById('my-node'), { quality: 0.95 }) .then(function (dataUrl) { var link = document.createElement('a'); link.download = 'my-image-name.jpeg'; link.href = dataUrl; link.click(); });

獲取 SVG 數據 URL,但篩選出所有元素:<i>

function filter (node) { return (node.tagName !== 'i'); } domtoimage.toSvg(document.getElementById('my-node'), {filter: filter}) .then(function (dataUrl) { /* do something */ });

使用每 4 個數組元素表示像素的RGBA 數據,將原始像素數據作為 Uint8Array 獲取:

var node = document.getElementById('my-node'); domtoimage.toPixelData(node) .then(function (pixels) { for (var y = 0; y < node.scrollHeight; ++y) { for (var x = 0; x < node.scrollWidth; ++x) { pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x); /* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */ pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4); } } });

impl 下的所有函數不是公共 API,並且僅公開用於單元測試。


渲染選項

濾波器

以 DOM 節點作為參數的函數。如果傳遞的節點應包含在輸出中(不包括節點意味着也不包括其子節點),應返回 true。未在根節點上調用。

bgcolor

背景顏色的字符串值,任何有效的 CSS 顏色值。

高度、寬度

渲染前要應用於節點的高度和寬度(以像素為單位)。

風格

在渲染之前要將其屬性復制到節點樣式的對象。您可能需要檢查此引用的CSS 屬性的 JavaScript 名稱。

質量

表示圖像質量的介於 0 和 1 之間的數字(例如 0.92 ±> 92%)JPEG 圖像。默認值為 1.0 (100%)

緩存布斯特

設置為 true 以將當前時間作為查詢字符串追加到 URL 請求,以啟用緩存破壞。默認值為 false

圖像位置持有人

獲取圖像時將使用的占位符圖像的數據 URL 失敗。默認值為未定義,並將對失敗的圖像引發錯誤

瀏覽器

它測試了最新的Chrome和Firefox(在編寫時分別是49和45),Chrome在大DOM樹上的表現明顯更好,可能是因為它更具有性能的SVG支持,而且它支持屬性。CSSStyleDeclaration.cssText

Internet 資源管理器不受(並且不會)支持,因為它不支持 SVG <外國對象>標記

Safari不受支持,因為它在 < 外國對象> 標記上使用更嚴格的安全模型。建議的解決方法是使用toSvg 並在服務器上呈現。`

依賴

當前僅使用標准 lib,但請確保您的瀏覽器支持:

  • 承諾
  • SVG 標簽<foreignObject>

測試

最重要的是,測試取決於:

  • js-imagediff,比較渲染和控制圖像

  • ocrad .js,對於無法比較圖像(由於瀏覽器呈現差異)時的部分,只需測試文本是否呈現

工作原理

也許有一天存在(或者可能已經存在?)一種將 HTML 的某些部分導出到圖像的簡單而標准的方法(然后這個腳本只能作為所有為了完成如此明顯的事情而必須跳過的所有圈套的證據),但到目前為止我還沒有找到一個。

此庫使用 SVG 的功能,允許在標記內具有任意 HTML 內容。因此,為了呈現該 DOM 節點,請執行以下步驟:<foreignObject>

  1. 遞歸克隆原始 DOM 節點

  2. 計算節點和每個子節點的樣式,並將其復制到相應的克隆

    • 不要忘記重新創建偽元素,因為它們不是任何形式的克隆,當然
  3. 嵌入 Web 字體

    • 查找可能表示 Web 字體的所有聲明@font-face

    • 解析文件 URL,下載相應的文件

    • 基64編碼和內聯內容作為 URLdata:

    • 連接所有處理的 CSS 規則,並將其放入一個元素中,然后將其附加到克隆<style>

  4. 嵌入圖像

    • 在元素中嵌入圖像 URL<img>

    • CSS 屬性中使用的內聯圖像,其方式類似於字體background

  5. 將克隆的節點序列化為 XML

  6. 將 XML 包裝到標記中,然后包裝到 SVG 中,然后將其作為數據 URL<foreignObject>

  7. 此外,若要將 PNG 內容或原始像素數據作為 Uint8Array 獲取,請創建一個圖像元素,將 SVG 作為源,並在屏幕外畫布上呈現它,您也創建了該畫布,然后從畫布上讀取內容

  8. 做!

需要注意的事情

  • 如果要渲染的 DOM 節點包含一個元素,該元素上繪制了一些內容,則應該處理得很好,除非畫布污染 - 在這種情況下,渲染將不成功。<canvas>

  • 在編寫本文時,Firefox 對一些外部樣式表有問題(請參閱問題#13)。在這種情況下,將捕獲並記錄錯誤。

作者

阿納托利·賽延科,保羅·巴考斯(原創想法)

許可證

麻省理工學院


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM