你一定在想截圖有甚麼好弄一篇文章的
前陣子有遇到一個特別的需求,希望原本的訂單紀錄的呈現,也可以讓使用者擷取下來保存或是處理後續工作,雖然使用者可以自行截圖,但為了簡化流程,希望「點一下」就能直接保存。
這次也很單純,搭配 html2canvas 來完成功能吧!
首先,要有擷取的目標:
<div
style={{
/* 都只是樣式 */
}}
>
<h5>Order Info</h5>
<p>Order No.: OR2210180002</p>
<p>Date: 2022/10/18</p>
<p>Customer: Charlie</p>
<p>Phone: 0912345678</p>
<hr />
<p>Book x1 $100</p>
<p>Book x1 $100</p>
<p>Total: $200</p>
</div>
非常陽春的樣子,再加上一顆下載用的按鈕:
使用方式如下:
html2canvas(document.querySelector("#capture")).then(canvas => {
document.body.appendChild(canvas)
});
可以知道要傳入的是 HTMLElement,並且是非同步的語法,大家都喜歡酷東西,所以async await 也是沒問題的:
async () => {
const canvas = await html2canvas(HTMLElement, options)
//後續對 canvas 操作
}
得到後的 canvas 就會長得跟原本的 element 有 99% 相似了。
文件有說,如果你的 element 有這些 style 通通會消失,使用上還請留意:
function useCapture({ fileName, ...options } = {}) {
const ref = useRef(null)
const handleCapture = async () => {
if (!ref.current) return
const canvas = await html2canvas(ref.current, options)
const link = document.createElement("a")
link.download = fileName || "image.png"
link.href = await canvas.toDataURL()
link.click()
}
return [ref, handleCapture]
}
useRef
透過這個 hook 來存取 DOM,把 ref
安裝在目標上。handleCapture
負責擷取的動作,透過創造 anchor
element,並進一步處理下載的動作:
canvas
canvas
轉換成 dataURL (這邊用預設的 png)anchor
並定義下載的檔案名稱與下載的目標fileName
可以定義下載後的檔案名稱options
則是參考 html2canvas 的文件即可再把對應的 ref 與 handler 塞到對應的地方,整體這樣就完成了!
雖然用到了 useRef
,但可以看出來整體非常的 JavaScript。
連假愉快