图片导出
前端实现图片导出的几种方式
问题
在前端如何将 Canvas、DOM 元素或 SVG 导出为图片并下载?
解答
1. Canvas 导出图片
// 获取 canvas 元素
const canvas = document.getElementById('myCanvas');
// 方式一:toDataURL - 返回 base64 字符串
const dataURL = canvas.toDataURL('image/png'); // 默认 png
const jpegURL = canvas.toDataURL('image/jpeg', 0.8); // jpeg,质量 0.8
// 方式二:toBlob - 返回 Blob 对象(推荐,性能更好)
canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
downloadImage(url, 'image.png');
URL.revokeObjectURL(url); // 释放内存
}, 'image/png');
// 通用下载函数
function downloadImage(url, filename) {
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
}
2. DOM 元素导出图片
使用 html2canvas 库将任意 DOM 元素转为图片:
import html2canvas from 'html2canvas';
async function exportDOMToImage(element, filename = 'export.png') {
// 将 DOM 转为 canvas
const canvas = await html2canvas(element, {
useCORS: true, // 允许跨域图片
scale: 2, // 提高清晰度
backgroundColor: '#fff'
});
// 导出下载
canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
});
}
// 使用
const element = document.getElementById('export-area');
exportDOMToImage(element, 'screenshot.png');
3. SVG 导出图片
function svgToImage(svgElement, filename = 'image.png') {
// 序列化 SVG
const svgData = new XMLSerializer().serializeToString(svgElement);
const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
const url = URL.createObjectURL(svgBlob);
// 创建 Image 加载 SVG
const img = new Image();
img.onload = () => {
// 绘制到 canvas
const canvas = document.createElement('canvas');
canvas.width = svgElement.width.baseVal.value || 300;
canvas.height = svgElement.height.baseVal.value || 150;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// 导出
canvas.toBlob((blob) => {
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = filename;
link.click();
URL.revokeObjectURL(downloadUrl);
});
URL.revokeObjectURL(url);
};
img.src = url;
}
4. 封装通用导出工具
const ImageExporter = {
// 下载 base64 图片
downloadBase64(dataURL, filename) {
const link = document.createElement('a');
link.href = dataURL;
link.download = filename;
link.click();
},
// 下载 Blob
downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
},
// Canvas 导出
fromCanvas(canvas, filename, type = 'image/png', quality = 1) {
return new Promise((resolve) => {
canvas.toBlob((blob) => {
this.downloadBlob(blob, filename);
resolve(blob);
}, type, quality);
});
},
// 远程图片下载(需处理跨域)
async fromURL(imageUrl, filename) {
const response = await fetch(imageUrl);
const blob = await response.blob();
this.downloadBlob(blob, filename);
}
};
// 使用示例
ImageExporter.fromCanvas(canvas, 'export.png');
ImageExporter.fromURL('https://example.com/image.jpg', 'download.jpg');
关键点
toDataURL返回 base64 字符串,toBlob返回 Blob 对象,后者内存效率更高- 导出后用
URL.revokeObjectURL()释放内存 - 跨域图片需要服务端配置 CORS,Canvas 中设置
crossOrigin="anonymous" html2canvas有局限性,部分 CSS 属性不支持(如box-shadow渲染可能有差异)- 提高导出清晰度可增大
scale或使用devicePixelRatio
目录