两款比较主流的截图工具
特性 | dom-to-image | html2canvas |
---|---|---|
体积 | 几 KB | 几十 KB |
速度 | 非常快 | 较慢 |
浏览器兼容性 | 与所有现代浏览器兼容 | 与部分浏览器兼容性较差 |
跨域截图 | 不支持 | 支持 |
自定义截图区域 | 不支持 | 支持 |
CSS 属性支持 | 不支持某些 CSS 属性 | 支持所有 CSS 属性 |
dom-to-image该库自 2020 年后基本处于维护状态,更新频率较低。这意味着它可能不会再添加新的功能,更多是对现有问题进行修复。 html-to-image:html-to-image是dom-to-image的一个分支,它继承了dom-to-image的核心功能,并且持续保持更新。开发者会不断添加新特性、优化性能和修复已知问题,社区活跃度相对较高。
安装与引用
//安装
npm install html2canvas
//引入
import html2canvas from 'html2canvas';
//安装
npm install html-to-image
//引入
import * as htmlToImage from 'html-to-image';
import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';
htmlToImage主要的方法有:
htmlToImage.toPng(…);将节点转化为png格式的图片
htmlToImage.toJpeg(…);将节点转化为jpg格式的图片
htmlToImage.toSvg(…);将节点转化为svg格式的图片,生成的图片的格式都是base64格式 htmlToImage.toBlob(…);将节点转化为二进制格式,这个可以直接将图片下载 htmlToImage.toPixelData(…);获取原始像素值,以Uint8Array 数组的形式返回,每4个数组元素表示一个像素点,即rgba值。这个方法也是挺实用的,可以用于WebGL中编写着色器颜色。
htmlToImage主要的属性有:
filter : 过滤器节点中默写不需要的节点;
bgcolor : 图片背景颜色;
height, width : 图片宽高;
style :传入节点的样式,可以是任何有效的样式;
quality : 图片的质量,也就是清晰度;//jpeg
cacheBust : 将时间戳加入到图片的url中,相当于添加新的图片;
imagePlaceholder : 图片生成失败时,在图片上面的提示,相当于img标签的alt;
1.img-(png,jpg)
- JPG:其完整名称是 Joint Photographic Experts Group,它实际上指的是由该专家小组制定的一种图像压缩标准。不过在日常生活和技术领域中,人们习惯用 “JPEG” 来表示采用此标准压缩的图像文件,并且文件扩展名常写成 “.jpg” 或者 “.jpeg”。该标准非常适合用于存储照片和色彩丰富的图像,因为它能在一定程度上平衡图像质量和文件大小。
- PNG:全称为 Portable Network Graphics,即便携式网络图形。它是作为替代 GIF 格式而开发的一种图像文件格式,支持无损数据压缩。PNG 格式在网页设计、图形设计以及需要透明背景效果的场景中应用广泛,因为它不仅能保证图像质量,还能实现良好的透明效果。
示例(react+ant-design):
const menuProps = {
items: exportFormat.map(item => ({
...item,
onClick: () => handleClick(item)
}))
}
①利用html2canvas
png,jpg核心:使用 html2canvas 将 <div> 渲染为 Canvas,然后导出为图片。
利用html2canvas转换:
JavaScript 库,可以将 DOM 元素渲染为 Canvas。它通过遍历 DOM 树,将每个元素的样式和内容绘制到 Canvas 上。
if (['jpg', 'png'].includes(item.label)) {
let canvas=await html2canvas(post.current)
//将 Canvas 的内容转换为 Base64 编码的图像数据 URL。
const image = canvas.toDataURL(`img/${item.label}`)
//创建一个 <a> 标签,设置其 href 为图像数据 URL,并触发点击事件来实现文件下载。
const link = document.createElement('a')
link.href = image
link.download = `post.${item.label}`
link.click()
}
②利用dom-to-image
if (['jpg', 'png'].includes(item.label)) {
const image = item.label === 'png' ? await htmlToImage.toPng(post.current, { bgcolor: 'white' }) : await htmlToImage.toJpeg(post.current, { quality: 0.95, bgcolor: 'white' });
const link = document.createElement('a');
link.href = image;
link.download = `post.${item.label}`;
link.click();
}
2.pptx
//安装
npm install pptxgenjs
//引用
import PptxGenJS from 'pptxgenjs';
if (['pptx'].includes(item.label)) {
console.log(222);
//利用html2canvas
const canvas = await html2canvas(post.current);
//将 Canvas 的内容转换为 Base64 编码的图像数据 URL。
const image = canvas.toDataURL('image/png');//方法1
//利用dom-to-image
const image=await htmlToImage.toPng(post.current)//方法2
const pptx = new PptxGenJS();
// 添加一张幻灯片
const slide = pptx.addSlide();
//x/y:距离幻灯片左边/右边的距离
//w/h:图片的大小 单位都为英寸
slide.addImage({ data: image, x: 1, y: 1, w: 4.5, h: 3 });
pptx.writeFile({ fileName: 'post.pptx' });
}
3.svg
html-to-image 的核心技术是利用SVG的 <foreignObject>
标签,将DOM节点嵌入到SVG中,然后将其转换为图像格式。
if (item.label === 'svg') {
// 获取 SVG 字符串-DataUrl形式
const svgString = await htmlToImage.toSvg(post.current);
// 提取并解码 URL 编码的 SVG 内容
const svgContent = decodeURIComponent(svgString.split(',')[1]);
// 创建 Blob 对象
const blob = new Blob([svgContent], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
// 创建下载链接
const link = document.createElement('a');
link.href = url;
link.download = 'post.svg';
link.click();
// 释放 URL 对象
URL.revokeObjectURL(url);
}
如果直接就是svg而不是dom元素:
const svgElement = post.current.querySelector('svg');
const serializer = new XMLSerializer();
const svgString = serializer.serializeToString(svgElement);
const blob = new Blob([svgString], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'post.svg';
link.click();
URL.revokeObjectURL(url);
无论是哪种方式,需要注意的是:
在将DOM元素导出为SVG时,直接使用XMLSerializer
或dom-to-image
等工具通常不会保留CSS样式,因为这些工具主要关注的是DOM结构和内联样式。为了确保导出的SVG包含CSS样式,您可以采取以下方法:
function inlineStyles(element) {
const computedStyle = window.getComputedStyle(element);
console.log(computedStyle);
for (let i = 0; i < computedStyle.length; i++) {
const property = computedStyle[i];
element.style.setProperty(property, computedStyle.getPropertyValue(property));
}
// 递归处理子元素
element.childNodes.forEach(child => {
if (child.nodeType === Node.ELEMENT_NODE) {
inlineStyles(child);
}
});
}
// 对内联 SVG 元素及其 <foreignObject> 内的元素应用内联样式
inlineStyles(svgElement);