iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Modern Web

React Hook 不求人,建立自己的 Hook Libary系列 第 25

[DAY 25] 自己的Hook自己做!html2canvas 來擷圖網頁的內容吧!

  • 分享至 

  • xImage
  •  

你一定在想截圖有甚麼好弄一篇文章的

DEMO 在這裡

情境

前陣子有遇到一個特別的需求,希望原本的訂單紀錄的呈現,也可以讓使用者擷取下來保存或是處理後續工作,雖然使用者可以自行截圖,但為了簡化流程,希望「點一下」就能直接保存。

需求與功能

這次也很單純,搭配 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

使用方式如下:

html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas)
});

可以知道要傳入的是 HTMLElement,並且是非同步的語法,大家都喜歡酷東西,所以async await 也是沒問題的:

async () => {
  const canvas = await html2canvas(HTMLElement, options)
  //後續對 canvas 操作
}

得到後的 canvas 就會長得跟原本的 element 有 99% 相似了。

留意 style 的支援

文件有說,如果你的 element 有這些 style 通通會消失,使用上還請留意:

Hook

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,並進一步處理下載的動作:
    1. html2canvas 將目標轉換成 canvas
    2. canvas 轉換成 dataURL (這邊用預設的 png)
    3. 建立 anchor 並定義下載的檔案名稱與下載的目標
    4. 點擊下載
  • fileName 可以定義下載後的檔案名稱
  • options 則是參考 html2canvas 的文件即可

再把對應的 ref 與 handler 塞到對應的地方,整體這樣就完成了!

DEMO 在這裡

結語

雖然用到了 useRef,但可以看出來整體非常的 JavaScript。

連假愉快


上一篇
[DAY 24] 自己的Hook自己做!useImage 來預覽圖片吧!
下一篇
[DAY 26] 自己的Hook自己做! 用 IntersectionObserver 弄出動態的網站吧!
系列文
React Hook 不求人,建立自己的 Hook Libary30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言