dom-to-image踩坑记录

2,334 阅读2分钟

之前调研过的需求HTML转PDF由于实现起来有诸多问题,产品最终决定把HTML转PDF需求降级为保存页面截图即可。所以采用dom-to-image来实现,代码如下:

const handleSaveImage = () => {

    setIsSaveImage(true) // 截图开始前先隐藏「生成图片」「下载数据」按钮避免fixed定位导致界面遮挡

    domtoimage

    .toJpeg(document.getElementById('EffectData'), { quality: 0.3, bgcolor: '#fff' })

    .then((dataUrl: string) => {

        const link = document.createElement('a')

        link.download = `${STAT_TASK_TYPE_TAN[type]}投后数据.jpeg`

        link.href = dataUrl

        link.click()

        setIsSaveImage(false)

    })
}

本来清清爽爽的代码完美实现需求,顺利通过了FireFox、Chorme的考验,在Safari浏览器挂了,页面里的echarts图表都显示不出来。无奈翻出官方文档和Github上的Issues来,遗憾的是并没有看到合理的解释。一番折腾无果,只得考虑换库html2canvas,这里记下一个教训下次再引用第三方库的时候一定要看清楚浏览器兼容性的介绍,避免重蹈覆辙。
用html2canvas实现截图功能代码如下:

html2canvas(document.querySelector("#EffectData"))

    .then(canvas => {

        const dataUrl = canvas.toDataURL("image/jpeg");

        const aLink = document.createElement('a');

        const blob = dataURLtoBlob(dataUrl)

        const evt = document.createEvent("HTMLEvents");

        evt.initEvent("click", true, true);//initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为

        aLink.download = 'test.jpeg'

        aLink.href = URL.createObjectURL(blob);

        aLink.click()

    })

    .catch((error: any) => {

        console.error('oops, something went wrong!', error)

    })

html2canvas中文使用文档
注意:
在实现截图的时候无论是dom-to-image还是html2canvas,如果被截图的dom元素内包含固定定位的子元素,最终截出的图都会被这个固定定位的子元素遮挡,所以需要额外处理。
用dom-to-image库的话就在截图前把固定定位的元素给隐藏掉(display:none),如果是用html2canvas,只需要给固定定位的元素或者不想被截图的元素添加data-html2canvas-ignore属性即可。

以上是本次实现截图需求遇到的坑点,记录下来与遭遇相同的人共勉。