html2canvas(document.querySelector('.content')).then(canvas => {
console.log(canvas);
// document.body.append(canvas)
const img = document.querySelector('.img');
img.src = canvas.toDataURL();
})
实现截图过程:
- 通过
关于window.devicePixelRatio
-
设备像素/物理像素
设备像素也被称为物理像素,它是显示设备中最小的物理部件。在同一设备中,物理像素的总数是固定的。 -
独立像素/CSS像素
CSS像素是一个抽象的单位,主要使用在浏览器上,用来精确的度量(确定)web页面上的内容。CSS像素被称为与设备无关的像素(device-independent像素),简称DIPs
在一个标准的显示密度下,一个CSS像素对应着一个设备像素。
window.devicePixelRatio
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/devicePixelRatio
返回当前显示设备的物理像素分辨率与CSS像素分辨率之比。简单来说,它告诉浏览器应使用多少屏幕实际像素来绘制单个CSS像素。
所以在标准屏幕下,devicePixelRatio应该为1。
特例
视网膜(Retina)显示屏,它会使用更多的屏幕像素绘制相同的对象,从而获得更清晰的图形。devicePixelRatio为2.
所以虽然一个DOM元素的CSS尺寸是375px,但是因为Apple是视网膜屏幕,所以使用了两倍于CSS尺寸的设备像素来渲染它,所以图片会变成750px。
html2canvas 坑
- 如果将window.devicePixelRatio设为1,那么如果存在box-shadow则会出现问题。
解决办法,在截图前将box-shadow属性覆盖掉 - 由于设置max-height造成滚动的问题
解决办法:在截图前将max-height去掉 - 其他问题
解决办法:在截图前做一些对应操作
截图图片并上传到oss上
思路:想canvas转换成Blob类型,然后上传。
function getCanvas2Blob(canvas: HTMLCanvasElement) {
return new Promise<Blob | null>(resolve => {
canvas.toBlob(blob => {
resolve(blob)
})
})
}
export async function uploadFile<R = any>(file: Blob, url='', fileName='img.png') {
const newFile = file instanceof File ? file : new File([file], fileName);
const formData = new FormData();
formData.append(newFile.name, newFile);
const { data } = await Axios.post<R>(url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
return data
}
补充知识点:
- File API接口:https://developer.mozilla.org/zh-CN/docs/Web/ API/File
- FormData API接口:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
html2canvas 截图的原理
目的:一个canvas元素,上面有绘制一系列的HTML节点
但是:canvas中没法添加具体的HTML节点,它只是一张画布
前置知识说明:
- 首先我们利用canvas具有drawImage() 的能力。
- SVG中有一个神奇的元素
foreignObject
文档地址:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/foreignObject
foreignObject元素允许包含来自不同XML命名空间的元素。在浏览器上下文中,很可能是XHTML/HTML

解决方案(即实现原理)
- 创建一个canvas元素和一个Image元素
- 在内存中创建svg元素,将html元素插入到svg中的foreignObject中
- 使用Blob构造函数,转换为原始二进制数据,再通过URL.createObjectURL() 将数据给Image的src。
- 再通过canvas的drawImage将图片绘制到canvas上。
- 这样,canvas上就有了dom节点的内容。
核心代码如下:
const element = document.querySelector('.element')
const data = `
<svg xmlns='http://www.w3.org/2000/svg' width='400px' height='400px'>
<foreignObject width='100%' height='100%' >
<div>
${element.innerHtml}
</div>
</foreignObject>
</svg>
`
const svg = new Blob([data], { type: 'image/svg+xml; charset=utf-8'})
const url = URL.createObjectURL(svg)
const image = new Image()
image.src = url
image.addEventListener('load', () => {
const ctx = canvas.getContext('2d')
if (ctx) {
ctx.drawImage(image, 0, 0)
}
})
本文探讨了window.devicePixelRatio的概念及其在不同设备上的应用,特别是在视网膜屏幕上。接着,文章深入讨论了html2canvas截图时遇到的问题,如box-shadow的渲染问题和max-height造成的滚动问题,并提供了相应的解决策略。最后,介绍了如何将canvas转换成Blob并上传到OSS,以及html2canvas截图的原理,涉及foreignObject元素在SVG中的作用。
1620

被折叠的 条评论
为什么被折叠?



