背景

结合后端数据生成运营推广页面,用户通过保存操作将推广页面保存为图片进行分享和传播。其中涉及到的前端主要技术点:

  1. dom转图片
  2. 保存图片到本地
了解 CORS

CORS(Cross-Origin Resource Sharing,跨域资源共享),同源安全策略默认阻止跨域获取资源,通过CORS给了Web服务器这样的权限,即服务器可以选择,允许跨域请求访问到它们的资源。CORS由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端JavaScript代码获取跨域请求的响应。

什么情况下需要CORS:

  1. XMLHttpRequestFetch发起的跨源HTTP请求。
  2. Web字体 (CSS中通过@font-face使用跨源字体资源)。
  3. WebGL贴图。
  4. 使用drawImageImages/video画面绘制到canvas
技术方案

html2canvas提供将dom绘制到canvasfile-saver:提供将Blob导出为本地文件。流程既是:
dom => html2canvas => canvas => blob => file-saver => image

import html2canvas from 'html2canvas';
import { saveAs } from 'file-saver';

const dom = document.getElementById('html-to-canvas')
html2canvas(dom, {
  useCORS: true,
})
  then(canvas => {
    const blob = canvas.toBlob((blod: Blob | null) => {
      if (blob) {
        saveAs(blob, 'html2canvas.png')
      }
    })
  })
问题与方案
跨域

由于canvas对于图片资源的同源限制,如果画布中包含跨域的图片资源则会污染画布,如上对于CORS介绍中用讲到使用drawImageImages/video画面绘制到canvas需要配合CORS使用。可以通过配置useCORS: true,且img标签配置crossOrigin = 'anonymous'支持CORS

跨域

资源加载不全

图片资源在生成快照是还未完全加载,造成快照内容不全,通过Promise.all保证图片资源加载完成,并开启快照生成功能。

// 加载图片
const toBlobURL = (url: string) => {
  return new Promise((resolve, reject) => {
    const canvasDom = window.document.createElement('canvas')
    const ctx = canvasDom.getContext('2d')
    const img = window.document.createElement('img')
    img.crossOrigin = 'anonymous'
    img.src = url
    
    img.onload = () => {
      canvasDom.width = img.width
      canvasDom.height = img.height
      ctx!.drawImage(img, 0, 0)

   	  canvasDom.toBlob((blob: Blob | null) => {
        if (blob) {
          const blobURL = URL.createObjectURL(blob)
    	  resolve(blobURL)
    	} else {
          reject()
        }
        })
      }

   img.onerror = () => {
     reject()
    }
  })
}

// 加载内容
const imgLists = imgContainerDom.querySelectorAll('img')
Promise.all(
  Array.from(imgLists).map((imgDom, i) => {
     return toBlobURL(imgDom.src)
  }),
)
  .then(res => {
    for (let i = 0; i < imgLists.length; i++) {
      imgLists[i].src = (res as any)[i]
  	}
  })
  .catch((e) => {
    console.log('enter error handle')
    console.log(e)
  })
微信导出不成功

issues:https://github.com/niklasvh/html2canvas/issues/2205
建议使用"html2canvas": "1.0.0-rc.4"
微信导出问题

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐