首先咱們不能直接把 HTML 畫到 canvas 上。咱們須要使用一個SVG 圖像包含想要呈現的內容 。爲了繪製 HTML 內容,你要先用<foreignObject>
元素包含 HTML 內容,而後再將這個 SVG 圖像繪製到你的 canvas 中。css
這裏的foreignObject
元素容許包含外來的XML命名空間,其圖形內容是別的用戶代理繪製的。這個被包含的外來圖形內容服從SVG變形和合成。html
咱們轉化的步驟爲:
1. 建立一個blob 對象, 其 MIME 應爲 「image/svg+xml」。
2. 一個 <svg>
元素。
3. 在 SVG 元素中包含的 <foreignObject>
元素。
4. 包裹到 <foreignObject>
中的(格式化好的) HTML。es6
也能夠直接用框架,效果更好。html2canvas.js。web
其實你想實現什麼效果,好比canvas轉化爲圖片的js,直接google百度上面一搜就好,一大堆ajax
老規矩, 先放圖canvas
第一個紅格子是DOM渲染的, 第二個帶邊框的紅格子是用html的代碼在canvas畫出來的, 沒有使用canvas的api哦. 本文最後貼出了代碼.api
本文轉化的實現, 以及本文下半部分所介紹的html2canvas.js框架的原理均出自於, mdn的這個篇文章將 DOM 對象繪製到 canvas 中
跨域
首先咱們不能直接把 HTML 畫到 canvas 上。咱們須要使用一個SVG 圖像包含想要呈現的內容 。爲了繪製 HTML 內容,你要先用<foreignObject>
元素包含 HTML 內容,而後再將這個 SVG 圖像繪製到你的 canvas 中。promise
這裏的foreignObject
元素容許包含外來的XML命名空間,其圖形內容是別的用戶代理繪製的。這個被包含的外來圖形內容服從SVG變形和合成。瀏覽器
咱們轉化的步驟爲:
1. 建立一個blob 對象, 其 MIME 應爲 「image/svg+xml」。
2. 一個 <svg>
元素。
3. 在 SVG 元素中包含的 <foreignObject>
元素。
4. 包裹到 <foreignObject>
中的(格式化好的) HTML。
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div class="wrapper"> <div class="target" style=" width: 100px; height: 100px; background: red; margin-bottom: 50px; ">123</div> </div> <canvas id="canvas" style="border:2px solid black;" width="200" height="200"> </canvas> <script> let canvas = document.getElementById('canvas'); let ctx = canvas.getContext('2d'); let target = document.getElementsByClassName('wrapper'); // 創造svg let data = ` <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <foreignObject width="100%" height="100%"> <div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px"> ${target[0].innerHTML} </div> </foreignObject> </svg> ` let DOMURL = window.URL || window.webkitURL || window; let img = new Image(); let svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'}); let url = DOMURL.createObjectURL(svg); // 根據svg生產url img.onload = function () { ctx.drawImage(img, 0, 0); DOMURL.revokeObjectURL(url); // 摧毀剛剛生產的url }// 註冊回調函數 img.src = url; // 將圖片url塞到img裏 </script> </body> </html>
有幾個須要注意的點:
1. 此方法中插入的html必須是有效的html
2. 必須使用內聯樣式, 而且支持部分樣式,
3. 已訪問的連接樣式(:visited
)不會對 SVG 圖像中的連接生效,所以沒法獲取瀏覽歷史;SVG 圖像中也不會渲染原生主題,所以藉此檢測用戶的平臺也會更困難。
4. 此外,您也不能在 SVG 圖像中各類引入腳本文件,所以不會有從其餘腳本文件訪問 DOM 的風險。SVG 圖像中的 DOM 元素也不能接收事件的輸入,所以沒法將敏感信息載入到一個表單控件(如將完整路徑載入到 file <input>
元素中)渲染再經過讀取圖像獲取這些信息。
5. 這個解決方案所依賴的 SVG 圖像在實現上是很是嚴格
的。若是引入了外部的圖片會污染canvas畫布. 可是接下來講介紹的html2canvas
能夠解決這個問題!!!
框架官網地址: http://html2canvas.hertzen.com/
本文使用介紹基於1.0.0-alpha.12版本
此次直接有框架生成的canvas, 所以沒有了邊框. 下面是代碼
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .target { width: 100px; height: 100px; background: red; margin-bottom: 50px; } </style> </head> <body> <div class="wrapper"> <div class="target">123</div> </div> <script src="./canvas.js"></script> <script> window.onload = function() { html2canvas(document.querySelector(".wrapper")).then(canvas => { document.body.appendChild(canvas) }); } </script> </body> </html>
.then
是promise語法, 不瞭解es6的同窗能夠看看阮一峯es6入門, 寫的很是好.
上面的代碼能夠看到, 支持內聯樣式了, 同時使用起來也很簡單. 那麼上文所留下的懸念: 如何加載外部圖片呢? 接下來將會和html2canvas的配置項一塊兒介紹給你們.
名稱 | 默認 | 描述 |
---|---|---|
async | true | 是否異步解析和渲染元素 |
allowTaint | false | 是否容許跨原始圖像污染畫布 |
backgroundColor | ffffff | 畫布背景顏色 |
canvas | null | 你本身提供一個canvas用做繪圖, 此項不填框架會自動生成一個canvas標籤 |
foreignObjectRendering | false | 就是是否用上面所提到的foreignObject這個來渲染, 默認爲遍歷dom樹 |
imageTimeout | 15000 | 設置圖像加載的超時時間(以毫秒爲單位)設置0爲禁用超時 |
ignoreElements | (element) => false | Predicate function which removes the matching elements from the render. 大體的意思是匹配元素, 在你渲染的時候去掉那個匹配的元素 |
logging | true | 啓用日誌記錄以進行調試 |
onclone | null | Callback function which is called when the Document has been cloned for rendering, can be used to modify the contents that will be rendered without affecting the original source document.這個我也不知道是幹嗎的, 歡迎你們踊躍提出建議 |
proxy | null | 填寫url, 設置代理,用於加載跨源圖像. 若是爲null,跨域圖片則不會加載 |
removeContainer | true | Whether to cleanup the cloned DOM elements html2canvas creates temporarily(還得研究, 不知道那個cloned DOM是幹嗎的) |
scale | window.devicePixelRatio | 設置渲染的比例。默認爲瀏覽器設備像素比率 |
useCORS | false | 是否嘗試使用CORS從服務器加載圖像 |
width | canvas寬度 | |
height | canvas高度 | |
X | Element x偏移量 | |
y | Element y偏移量 |
圖片隨便在網上找的
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> img { width: 500px; } </style> </head> <body> <div class="wrapper"> <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1533212152031&di=f26250570f7d5f2e7895c7c13e96d61a&imgtype=0&src=http%3A%2F%2Fh.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F267f9e2f07082838304837cfb499a9014d08f1a0.jpg"></img> </div> <script src="./canvas.js"></script> <script> window.onload = function() { html2canvas(document.querySelector(".wrapper"), { allowTaint: true, useCORS: true, }).then(canvas => { document.body.appendChild(canvas) }); } </script> </body> </html>
ps: 若是在小瓶圖片變糊, 能夠試着設置那個scale參數, 或者採用在canvas的width屬性設置例如1000, 在css中設置width: 500px; 來進行壓縮
若是你須要保存爲本地圖片能夠採用Canvas2Image.js這個框架, 具體內容百度, 本文不作介紹
參考:HTML如何轉化爲canvas教程 - 翾的博客 - CSDN博客https://blog.csdn.net/c_kite/article/details/81364592