html2canvas的踩坑之路

Anonlyyy發表於2018-06-27

前言

早有耳聞這個html2canvas比較坑,但無奈於產品需求的壓迫,必須實現html轉圖片的功能,自此走上了填坑之路,好在最後的效果還算令人滿意,這才沒有誤了產品上線週期.

html2canvas介紹

html2canvas的詳細介紹可以點選這裡檢視,其實簡單來說就是通過canvasHTML生成的DOM節點繪製到畫布上,再可以通過自己的需求轉換成圖片.所以官方文件也說了,最後生成的效果不是100%相同的,這一點大家要有心理準備,無論怎樣,一點點小瑕疵是肯定有的。

相容性

html2canvas的踩坑之路
PS:微信瀏覽器使用也是沒有問題的哦

使用html2canvas

使用也是十分簡單,官網寫的很清楚戳這裡

踩坑過程

生成的圖片裡面為什麼缺失微信頭像或其他圖片?

其實涉及到的就是跨域問題,即便是canvas的畫布中對於圖片的域也是有要求的,那我們應該怎麼解決呢?

  1. html2canvas配置項中配置 allowTaint:trueuseCORS:true(二者不可共同使用)
  2. img標籤增加 crossOrigin='anonymous'
  3. 圖片伺服器配置Access-Control-Allow-Origin 或使用代理

其中第三步是最重要的,不設定則前兩步設定了也無效。

伺服器需要配置Access-Control-Allow-Origin資訊,如PHP新增響應頭資訊,*萬用字元表示允許任意域名:

header("Access-Control-Allow-Origin: *");
複製程式碼

或者指定域名:

header("Access-Control-Allow-Origin: www.zhangxinxu.com");
複製程式碼

但如果不想麻煩後端的人員,那我們前端怎麼跨域呢? 那就可以使用代理外掛,如: html2canvas-proxy-nodejs 或者是 superagent,我是使用superagent,貼一下示例程式碼:

const request = require('superagent') // 匯入
const proxHost = 'https://thirdwx.qlogo.cn' // 指定跨域圖片的地址
app.use('/proxy', function (req, res, next) {
  let urlPath = req.url
  console.log('urlPath', urlPath)
  urlPath = decodeURI(urlPath)
  if (!urlPath) {
    console.log('urlPath is null')
    return next()
  }
  console.log('proxy-request: /proxy->' + `${proxHost}${urlPath}`)
  const reqStream = request.get(`${proxHost}${urlPath}`)
  reqStream.on('error', function (err) {
    console.log('error', err)
  })
  console.log('------reqStream----')
  return reqStream.pipe(res)
})
複製程式碼

那麼最終我在頁面中的圖片的srchttps://thirdwx.qlogo.cn/xxx 要更改為/proxy/xxx 效果圖如下:

html2canvas的踩坑之路

2.生成的圖片模糊不清且有鋸齒瑕疵怎麼辦?

大部分找到的結果都是使用裝置畫素比去操作,但實際使用起來,還是會有鋸齒。 這個問題苦惱了我很久,並且找了很久的相關資料,總算是功夫不負有心人,讓我找到了解決方案,在github裡有大神已經提供瞭解決方案,可以點選這裡,大神在原始碼的基礎上增加兩個配置項,scaledpi,推薦使用scale引數。

原始碼位置:https://github.com/eKoopmans/html2canvas/tree/develop/dist

        let imgHeight = window.document.querySelector('.content').offsetHeight // 獲取DOM高度
        let imgWidth = window.document.querySelector('.content').offsetWidth // 獲取DOM寬度
        let scale = window.devicePixelRatio // 獲取裝置畫素比
        html2canvas(window.document.querySelector('.content'), {
            useCORS: true,
            scale: scale,
            width: imgWidth,
            height: imgHeight
        }).then((canvas) => {
          window.document.querySelector('.content').remove()
          let elemImg = `<img src='${canvas.toDataURL('image/png')}' id='canvas-img' style='height: ${imgHeight}px;border-radius: 10px;width:${imgWidth}px'/>`
          window.document.querySelector('.container').innerHTML = elemImg
        })
複製程式碼

最終生成出來的圖片,是清晰並且最接近DOM的圖片

3.生成的圖片中若包含二維碼,微信長按圖片偶現無法識別?

html2canvas的踩坑之路
這個問題主要出現在使用單頁面框架(如VUE)的頁面. 感謝 sundaypig提出的解決方案。 很簡單,就是不使用路由切換,使用window.location.href直接跳轉重新整理頁面

    location.href="www.abc.com/share/xxx"
複製程式碼

PS:這個問題可以解決所有頁面中偶現二維碼無法識別的情況

4.生成的圖片中文字間距較大?

這個暫時無法完美解決,可以嘗試用css屬性:letter-spacing來設定字間距