共计 3438 个字符,预计需要花费 9 分钟才能阅读完成。
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.
正文完