Problem

应用html2canvas.js解决浏览器截屏时,发现当元素宽度超过某个阈值后会呈现超出局部渲染异常现象。

Debug

html2canvas截屏,本质是dom转canvns,canvas转图片。

指标宽度20000+px

  • 无操作,copyDom显示失常,canvas宽高失常,但右侧元素显示为黑块,且地位居左。
  • option增加foreignObjectRendering: true,copyDom显示失常,canvas宽高失常,但右侧原异样元素缺失局部文本。
  • option指定width为10000,copyDom显示失常,canvas宽度10000,导出10000宽-图失常。

初步推断canvas渲染有宽度下限,百度一番仍无定论

Solution

首先不是视图外元素缺失的问题,试了很多都无后果。最初敲定折中计划就是依据宽度计算 拆分出图。

Old code

/** * @description html转图片导出 * @param ele * @param option * @param fileName * @param uuidKey */export const handleHtml2Down = (ele, option, fileName, uuidKey) => {    window.pageYOffset = 0;    document.documentElement.scrollTop = 0    document.body.scrollTop = 0    const targetDom = document.querySelector(ele)    const copyDom = targetDom.cloneNode(true)    copyDom.style.width = targetDom.scrollWidth + 'px'    copyDom.style.height = targetDom.scrollHeight + 'px'    copyDom.style.position = 'absolute'    copyDom.style.top = '0px'    copyDom.style.zIndex = '-1'    copyDom.style.backgroundColor = 'white'    document.body.appendChild(copyDom)    html2canvas(copyDom, {        height: copyDom.scrollHeight,        width: copyDom.scrollWidth,        allowTaint: false,        useCORS: true,        ...option    }).then((canvas => {        copyDom.parentNode.removeChild(copyDom)        canvas.style.width = parseFloat(canvas.style.width) * 0.8 + 'px'        canvas.style.height = parseFloat(canvas.style.height) * 0.6 + 'px'        let imgURL = canvas.toDataURL('image/png',1.0)        const alink = document.createElement("a")        alink.href = imgURL        let theName =  fileName || getUUID(uuidKey)        alink.download = `${theName}.png`        alink.click()    }))}

New code

/** * @description html转图片导出【宽度分页】 * @param ele 指标dom元素 * @param option html2canvas函数执行参数 * @param fileName 导出图片文件(可不传) * @param uuidKey uuid前缀字符(可不传) */export const handleHtml2Down = async (ele, option, fileName, uuidKey) => {    //  reset this page scroll    window.pageYOffset = 0;    document.documentElement.scrollTop = 0    document.body.scrollTop = 0    //  targetDom - target 2 img    const targetDom = document.querySelector(ele)    //  copyDom - copy dom from targetDom    const copyDom = targetDom.cloneNode(true)    //   copyWrapper - wrapper contain the copyDom , use for with-overflow    const copyWrapper = document.createElement('div')    //  init the copyDom    copyDom.style.width = targetDom.scrollWidth + 'px'    copyDom.style.height = targetDom.scrollHeight + 'px'    copyDom.style.transform = ''    copyDom.style.margin = '0 0'    //  define the maxWidth:15000(px)    const maxW = 15000    //  define the val    let urls = [], w = targetDom.scrollWidth,index=0    //  init the copyWrapper    copyWrapper.style.backgroundColor = 'white'    copyWrapper.style.width = (w > maxW ? maxW : w) + 'px'    copyWrapper.style.height = targetDom.scrollHeight + 'px'    //  fix the element    copyWrapper.style.position = 'fixed'    copyWrapper.style.top = '0px'    //  make sure the copyWrapper is invisible    copyWrapper.style.zIndex = '-1'    //  use for pageControl    copyWrapper.style.overflow = 'hidden'    //  execute dom append    copyWrapper.appendChild(copyDom)    document.body.appendChild(copyWrapper)    //  generate canvas from dom in Loop    while (w > 0){        await html2canvas(copyWrapper, {            height: copyWrapper.scrollHeight,            width: (w > maxW ? maxW : w),            foreignObjectRendering: true,            allowTaint: false,            useCORS: true,            ...option        }).then((canvas => {            canvas.style.width = parseFloat(canvas.style.width) * 0.8 + 'px'            canvas.style.height = parseFloat(canvas.style.height) * 0.6 + 'px'            urls.push(canvas.toDataURL('image/png',1.0))            w = w - maxW            index++            copyWrapper.style.width = w            copyDom.style.marginLeft = `-${maxW * index}px`        }))    }    //  execute dom remove    copyDom.parentNode.removeChild(copyDom)    console.log(urls)    //  export urls & execute img download    urls.forEach(url=>{        let alink = document.createElement("a")        alink.href = url         alink.download = `${fileName || getUUID(uuidKey)}.png`        alink.click()    })}expory getUUID = (preffix)=> { return preffix + 'i-am-uuid-123'}

Result


End

thanks 4 read & welcome 4 leaving a message.