html生成縮略圖來預覽解決方案
一、總結
一句話總結:先將html轉化為canvas,然后將canvas生成圖片ajax上傳到服務器,就可以了
html 轉化 canvas 圖片 上傳 html2canvas.js
1、如何將html轉化為canvas?
SVG foreignObject元素
html2canvas.js
首先我們不能直接把 HTML 畫到 canvas 上。我們需要使用一個SVG 圖像包含想要呈現的內容 。為了繪制 HTML 內容,你要先用<foreignObject>
元素包含 HTML 內容,然后再將這個 SVG 圖像繪制到你的 canvas 中。
這里的foreignObject
元素允許包含外來的XML命名空間,其圖形內容是別的用戶代理繪制的。這個被包含的外來圖形內容服從SVG變形和合成。
我們轉化的步驟為:
1. 創建一個blob 對象, 其 MIME 應為 “image/svg+xml”。
2. 一個 <svg>
元素。
3. 在 SVG 元素中包含的 <foreignObject>
元素。
4. 包裹到 <foreignObject>
中的(格式化好的) HTML。
也可以直接用框架,效果更好。html2canvas.js。
2、canvas轉化為圖片的框架?
Canvas2Image.js
其實你想實現什么效果,比如canvas轉化為圖片的js,直接google百度上面一搜就好,一大堆
二、HTML如何轉化為canvas教程
預覽圖
老規矩, 先放圖
第一個紅格子是DOM渲染的, 第二個帶邊框的紅格子是用html的代碼在canvas畫出來的, 沒有使用canvas的api哦. 本文最后貼出了代碼.
原理
本文轉化的實現, 以及本文下半部分所介紹的html2canvas.js框架的原理均出自於, mdn的這個篇文章將 DOM 對象繪制到 canvas 中
首先我們不能直接把 HTML 畫到 canvas 上。我們需要使用一個SVG 圖像包含想要呈現的內容 。為了繪制 HTML 內容,你要先用<foreignObject>
元素包含 HTML 內容,然后再將這個 SVG 圖像繪制到你的 canvas 中。
這里的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
可以解決這個問題!!!
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的配置項一起介紹給大家.
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