html2canvas插件的优化使用

253 阅读2分钟

插件地址

我在使用这个插件的时候,主要想解决的一个问题就是想将一个dom转成base64的数据存储起来,然后在特定环境下不渲染dom,直接用img标签的src,这样能减少页面的渲染时间,

  1. 首先我使用了btoa的全局方法,发现编码之后的结果没有前缀data:{MIMETYPE}XXX,然后我尝试主动添加前缀来支持src上的渲染,结果以失败告终

  2. 然后我人才市场找到了html2canvas这个库来支持我完成需求,接着按部就班:install==》import ==》html2canvas(XXX),得到的canvas调用toDataURL方法就可以得到base64数据

  3. 结果却是能生成我所需的base64数据也能渲染到img标签上,接着问题又来了,当你的元素中渲染了大量的div、style、svg的数据,插件会从head到body,从上到下依次访问dom,这个耗时会在10s以上甚至更长

  4. 根据插件的文档我得到了两个解决途径:降低分辨率和减少dom的clone。

    option的scale来降低分辨率,发现耗时没任何变化,那就说明只有减少dom的clone才能解决问题

    在打印出ignoreElements的回调参数之后我发现,当回调返回false的时候,下一次就会进入下一层dom,否则就遍历访问同级dom,所以判断是否和当前需要导出的dom相关的内容被访问,我们就可以减少耗时, 其中我就用到了compareDocumentPosition方法,它可以判断出两个dom的关系,具体可以看官方文档 下面是我实现功能的具体代码,有任何疑问或者改进方法,可以评论区讨论。

public async toDataUrl() {
  const canvas = await html2canvas(this.textRef, {
    windowHeight: this.textRef.clientHeight, 
    windowWidth: this.textRef.clientWidth,
    scale: 0.8,
    ignoreElements: ((element: any) => {
      console.log(element, element.compareDocumentPosition(this.textRef), element == this.textRef)
      if (element.tagName === 'HEAD') {
        return false
      } else if(element.tagName === 'STYLE') {
        return false
      } else if (element.compareDocumentPosition(this.textRef) === 8 || element.compareDocumentPosition(this.textRef) === 20) {
        return false
      } else if (element == this.textRef || element.compareDocumentPosition(this.textRef) === 10) {
        return false
      } else {
        return true
      }
    })
  })
  return canvas.toDataURL('image/png')
}```