透過JavaScript將HTML轉為圖檔
43 |
最近寫了小工具用ASP.NET MVC及Knockout讀取跑道計圈GPS資料轉成HTML表格,當成運動記錄的圖檔附件,但每次產生HTML表格後都得用螢幕擷取工具將網頁畫面另存圖檔,雖然手續還算單純,但你知道,懶惰是沒有極限的,我開始動腦筋,打算將產生圖檔的動作也自動化。
薑薑薑薑~ 如上圖所示,真的被我找到方法! 一切要感謝神奇的程式庫—html2canvas,它可以將整張網頁或局部元素轉為HTML5 Canvas,一旦轉成Canvas,匯出圖檔便是小事一椿囉!
html2canvas的原理並非擷取網頁畫素,而是解析DOM及CSS的所有細節,在HTML5 Canvas裡以線、矩形、圓弧、文字... 等試著模擬出相同外觀,因此產出結果可能有細微誤差,也存在無法讀取跨網域內容的限制,但經實際使用,效果已讓人滿意,html2canvas幾乎是用Canvas打造出靜態網頁瀏覽器引擎,是神人級的作品。(咦? 我怎麼跪著寫範例程式... )
範例程式碼如下,有興趣的朋友也可試玩看看:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML to Image</title>
<style>
table { background-color: #ccddff; }
td { padding: 2px 6px; }
table input {
width: 100px; padding: 2px 6px;
color: blue; border: 1px solid gray;
}
fieldset { width: 200px; height: 120px; margin-top: 6px; }
</style>
</head>
<body>
<table>
<tr><td>姓名</td><td><input value="Darkthread"></td></tr>
<tr><td>積分</td><td><input value="9999"></td></tr>
</table>
<hr />
<input type="button" value="轉為圖檔" />
<a></a>
<fieldset>
<legend>圖檔</legend>
<div>
</div>
</fieldset>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.js "></script>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js "></script>
<script src="http://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script>
$(":button").click(function() {
html2canvas($("table")[0]).then(function(canvas) {
var $div = $("fieldset div");
$div.empty();
$("<img />", { src: canvas.toDataURL("image/png") }).appendTo($div);
});
});
</script>
</body>
</html>
Comments
# by Randolph
我今天研究了上傳圖片檔時先在瀏覽器 Resize 再上傳檔案的程式碼。 它會用到你最近使用的 Canvas 及相關 HTML5 新物件。 應該蠻適合你最近對於 HTML5 的研究,不知道你有沒有興趣研究看看。
# by 小胖
我有興趣 @@"
# by 小孟
請問有辦法直接執行PAGE時就變成圖檔嗎?
# by Jeffrey
to 小孟, 不明白「直接執行PAGE時就變成圖檔」的定義,需要再進一步解釋。
# by 豆沙包
想請問 這個可以調整儲存圖片的解析度嗎?? 我們儲存以後列印出來解析度不夠 文字都有點糊糊的 想請問該怎樣解決
# by Jeffrey
to 豆沙包,html2canvas基本上是用螢幕的解析度產生圖檔,與列印的理想解析度有段距離(96DPI vs 300DPI),針對這問題github有一串討論( https://github.com/niklasvh/html2canvas/issues/241 ),有人想到用CSS把網頁放大N倍再匯出成圖檔的解決方案,你可以參考看看。
# by danny
請問: html2canvas($("table")[0]這裡我有看懂是把table中的都輸出,想說說,如果我有很多div要分開來輸出是否可以? 例如: <div class="a">文字1</div> <div class="a">文字2</div> <div class="a">文字3</div> 我試著改成html2canvas($(".a"))....都只會把"文字1"變圖而已,"文字2"之後的就不行了, 請問有解嗎? ^__^
# by Jeffrey
to danny, 應寫成 $(".a").each(function() { html2canvas(this, ....); }); 範例:http://output.jsbin.com/hifibi
# by danny
Jeffery 感謝解惑 ^_^, 再請問, 例如: <div class="a">文字1</div> <div class="b">文字2</div> <div class="b">文字3</div> 只要是class="a"的div中"文字1"就直接變圖, 這是否可行?
# by Jeffrey
to danny, 不太理解「只要是class="a"的div中"文字1"就直接變圖」,需要更完整的說明才能幫忙。
# by danny
Sorry Jeffrey 沒講清楚 @_@, 假設頁面中會有很多個class="a"的div, 但都在不同的位置 1. <div class="a">想變圖的字</div> 2. <div class="b">一般文字</div> 3. <div class="a">想變圖的字</div> 只要是被class="a" div包住的內容都會輸出成圖, 再請解惑了~
# by Jeffrey
to danny, http://jsbin.com/jebibu 你的需求一樣寫$(".a").each(…) 即可,程式不需修改。
# by danny
Jeffrey 感謝熱心的協助且解惑, 真得獲益良多 @_^~
# by Jim
我想問一下 我出的同時想把圖片等比例放大會有辦法做到麼 例如我的div尺寸為 640*360想輸出時為1280*720 第二個問題是 我想在IE8也使用此功能有甚麼方法麼?
# by Jeffrey
to Jim, 直接放大圖檔會產生鋸齒,我建議放大 div 尺寸再用放大後的 div 轉圖檔效果會較好。IE8 不支援 HTML5 Canvas,非做不可的話要依賴 Flash、Java Applet、Silverlight、ActiveX…,但這堆都算過時技術,現階段再投入研究不符效益,建議慎重評估。
# by ThankU
請問, 如何直接把產出的圖存檔?
# by Jeffrey
to ThankU, 請參考這篇:http://blog.darkthread.net/post-2011-10-30-html5-canvas-sktechpad.aspx
# by Ricky
radio 變成圖片的時候是空白的 有辦法解決嗎
# by Jeffrey
to Ricky, 能否提供jsbin範例重現問題?
# by Ricky
請問圖片能夠傳進網站暫存器中 然後再傳給php檔做圖片上傳至資料庫嗎
# by Jeffrey
to Ricky, 你所說的需求對 PHP 或其他 Web Server 語言來說都不難實現,不過我對 PHP 了解不多,沒法提供更詳細的補充。
# by Ken
如果擷取的內容裡有外連圖片 會擷取不到 請問有辦法解決嗎?
# by Jeffrey
to Ken, 有個做法是在同網站寫一支中間程式,傳入URL請它抓取圖檔後回傳,以突破瀏覽器無法擷取外部網站內容的安全限制。但要注意此中間程式可能被當成惡意攻擊的跳板,應加上來源IP或使用者身分限制。
# by WilliamLin
大大你好,如果我是在地圖上畫線 然後用html2canvas做截圖的動作 但是有時候圖片只有包含地圖卻沒有線 可以請問這是出在哪邊的問題呢? 謝謝!
# by Jeffrey
to WilliamLin, 如果你能提供 jsbin.com 或 jsfiddle.net 上的可執行範例,大家比較容易幫忙查問題。
# by Ken
請問文章內範例的程式碼是不是失效了
# by Jeffrey
to Ken, 文章因年代久遠,歷經滄海桑田,html2canvas 搬了位置也換了版本,新版寫法也改了,要用 Promise 處理事件,已更新程式範例,Have Fun!
# by Ken
原來如此,感謝大大。
# by Jeremy
請問轉成圖檔顯示時可以調整大小嗎,我在您的表格上面用input放圖片然後用div把圖和表格包起來,再用html2canvas顯示出來是原始大小,我希望可以小一點而不是整個畫面,而且如果有圖片的狀況下,表格內的字有時候會消失,出來的圖片就是圖+沒字的表格。
# by Angela
您好,不好意思想請教您,有沒有不需先預覽就可存成圖檔的方式呢?
# by kent
您好,如果想將網頁元素轉圖片再轉成陣列給Arduino的LED顯示,有比較可行的方向嗎?
# by Jeffrey
to kent, 要看你 Arduino LED 顯示要吃什麼格式的輸入資料,是 8x8 矩陣嗎? https://xantorohara.github.io/led-matrix-editor/
# by kent
您好,主要是一個8X8的矩陣,與一個111X202的電子紙,想要將網頁轉圖像,再將圖像轉成文字給學生複製下來貼上下面的函式庫https://github.com/ZinggJM/GxEPD 而8X8的矩陣可能直接用您提供的就可以了 謝謝
# by joy
您好! 我想請問可以把存下的png檔背景為透明嗎?
# by Jeffrey
to joy, 我想到兩個解決方向:1. 修改 html2canvas,將 DOM 繪製到 Canvas 時改用透明背景色(難度較高) 2. 將 DOM 的背景部分設成可明顯區隔的特定背景色,輸出 png 後再加工將特定背景色換成透明色。
# by 金城武
您好,請教您,有沒有不需先預覽就可存成圖檔的方式呢?
# by Jeffrey
to 金城武,是指按鈕後直接下載圖檔?
# by jean
想請問這在 IE 會正常嗎 ? 因為看到 code 中有用到 .then()
# by Jeffrey
to jean, 支援 IE9+,但 IE 要用需載入Promise polyfill,詳情可參考 https://github.com/niklasvh/html2canvas
# by Hua
您好 請問如果出現以下訊息: Failed to load resource: net::ERR_INVALID_URL 這是哪個部分出問題呢?
# by Jeffrey
to Hua, 感覺像是圖檔 Data URI 不正確造成的,試著加一行 console.log(canvas.toDataURL("image/png")) 把它印出來檢查看看。
# by jerry
您好: 太強了 但請問IE11 按轉為圖檔 沒有動作, (GOOGLE chrome 就OK) 如何讓IE11可以正常運作 謝謝~~
# by jerry
謝謝您 我有找到了 多加 <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script>