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.