html2canvas与window.devicePixelRatio

本文探讨了window.devicePixelRatio的概念及其在不同设备上的应用,特别是在视网膜屏幕上。接着,文章深入讨论了html2canvas截图时遇到的问题,如box-shadow的渲染问题和max-height造成的滚动问题,并提供了相应的解决策略。最后,介绍了如何将canvas转换成Blob并上传到OSS,以及html2canvas截图的原理,涉及foreignObject元素在SVG中的作用。
部署运行你感兴趣的模型镜像

官方文档

html2canvas(document.querySelector('.content')).then(canvas => {
    console.log(canvas);
    // document.body.append(canvas)
    const img = document.querySelector('.img');
    img.src = canvas.toDataURL();
})

实现截图过程:

  1. 通过

关于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 坑

  1. 如果将window.devicePixelRatio设为1,那么如果存在box-shadow则会出现问题。
    解决办法,在截图前将box-shadow属性覆盖掉
  2. 由于设置max-height造成滚动的问题
    解决办法:在截图前将max-height去掉
  3. 其他问题
    解决办法:在截图前做一些对应操作

截图图片并上传到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
}

补充知识点:

html2canvas 截图的原理

目的:一个canvas元素,上面有绘制一系列的HTML节点
但是:canvas中没法添加具体的HTML节点,它只是一张画布

前置知识说明:
  1. 首先我们利用canvas具有drawImage() 的能力。
  2. SVG中有一个神奇的元素foreignObject
    文档地址:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/foreignObject
    foreignObject元素允许包含来自不同XML命名空间的元素。在浏览器上下文中,很可能是XHTML/HTML
    在这里插入图片描述
解决方案(即实现原理)
  1. 创建一个canvas元素和一个Image元素
  2. 在内存中创建svg元素,将html元素插入到svg中的foreignObject中
  3. 使用Blob构造函数,转换为原始二进制数据,再通过URL.createObjectURL() 将数据给Image的src。
  4. 再通过canvas的drawImage将图片绘制到canvas上。
  5. 这样,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)
    }
})

补充知识:
new Blob() 和 URL.createObjectURL()

您可能感兴趣的与本文相关的镜像

GPT-oss:20b

GPT-oss:20b

图文对话
Gpt-oss

GPT OSS 是OpenAI 推出的重量级开放模型,面向强推理、智能体任务以及多样化开发场景

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

. . . . .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值