Problem
使用html2canvas.js
处理浏览器截屏时,发现当元素宽度超过某个阈值后会出现超出部分渲染异常现象。
Debug
html2canvas截屏,实质是dom转canvns,canvas转图片。目标宽度20000+px
- 无操作,copyDom显示正常,canvas宽高正常,但右侧元素显示为黑块,且位置居左。
-
文章图片
option
添加foreignObjectRendering: true
,copyDom显示正常,canvas宽高正常,但右侧原异常元素缺失部分文本。-
文章图片
option
指定width为10000,copyDom显示正常,canvas宽度10000,导出10000宽-图正常。
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 = https://www.it610.com/article/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 = https://www.it610.com/article/url
alink.download = `${fileName || getUUID(uuidKey)}.png`
alink.click()
})
}
expory getUUID = (preffix)=> { return preffix + 'i-am-uuid-123'}
Result
文章图片
文章图片
End 【html2canvas 目标元素过长canvas渲染不全【折中方案】】thanks 4 read & welcome 4 leaving a message.