我在使用这个插件的时候,主要想解决的一个问题就是想将一个dom转成base64的数据存储起来,然后在特定环境下不渲染dom,直接用img标签的src,这样能减少页面的渲染时间,
-
首先我使用了btoa的全局方法,发现编码之后的结果没有前缀data:{MIMETYPE}XXX,然后我尝试主动添加前缀来支持src上的渲染,结果以失败告终
-
然后我人才市场找到了html2canvas这个库来支持我完成需求,接着按部就班:install==》import ==》html2canvas(XXX),得到的canvas调用toDataURL方法就可以得到base64数据
-
结果却是能生成我所需的base64数据也能渲染到img标签上,接着问题又来了,当你的元素中渲染了大量的div、style、svg的数据,插件会从head到body,从上到下依次访问dom,这个耗时会在10s以上甚至更长
-
根据插件的文档我得到了两个解决途径:降低分辨率和减少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')
}```