canvas导出图片可通过todataurl(适合小图,返回base64)或toblob(推荐大图,内存友好、支持promise)实现,结合a标签下载;需注意跨域、透明背景、高dpi适配等问题。

Canvas 画布内容可以通过 toDataURL() 或 toBlob() 方法转为图片数据,再结合 a 标签触发下载,实现导出为 PNG、JPEG 等格式的文件。
使用 toDataURL 生成 base64 并下载
toDataURL() 返回一个 base64 编码的字符串,默认是 PNG 格式。适合小尺寸画布,但大图可能因 URL 长度限制在某些浏览器中失败。
- 调用
canvas.toDataURL('image/png')(PNG)或canvas.toDataURL('image/jpeg', 0.9)(JPEG,第二个参数为质量,0–1) - 创建
<a></a>元素,设置href为该 data URL,download属性指定文件名 - 调用
a.click()触发下载
示例:
用户要生成可打印的中文字帖/练习纸、导出多页 A4 PDF 报告,或把 SVG 设计稿零误差还原到 Canvas 时使用。本技能是「Canvas 内容工厂闭环」的总控,编排:网格渲染引擎(13 种教育网格+拼音标注) → 多页 PDF 导出(A4 合成) → SVG 精准复刻(坐标误差<0.001px)。触发词:生成字帖、练习纸、导出 PDF、SVG 转 Canvas、印刷级还原、A4 报告、米字格田字格。
function downloadCanvasAsPNG(canvas, filename = 'canvas.png') {
const url = canvas.toDataURL('image/png');
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
推荐用 toBlob 处理大图和更好兼容性
toBlob() 直接生成 Blob 对象,不经过 base64,内存更友好,且支持 Promise 化(现代写法),是导出大画布的首选方式。
- 调用
canvas.toBlob(callback, type, quality),callback 接收 Blob 参数 - 用
URL.createObjectURL(blob)创建临时 URL - 同上,通过
<a></a>下载,注意下载后调用URL.revokeObjectURL()释放内存
示例(Promise 封装):
function downloadCanvasAsJPEG(canvas, filename = 'canvas.jpg', quality = 0.95) {
return new Promise((resolve, reject) => {
canvas.toBlob(
blob => {
if (!blob) {
reject(new Error('Canvas is empty or too large'));
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
resolve();
},
'image/jpeg',
quality
);
});
}
注意事项与常见问题
-
跨域图像限制:若 Canvas 绘制了来自其他域名的图片(如
<img src="https://...?x-oss-process=image/resize,p_40">),未设置CrossOrigin会导致toBlob/toDataURL抛错或返回空。解决方法:图片加载前设img.crossOrigin = 'anonymous',且服务端需允许 CORS -
透明背景处理:导出为 JPEG 时透明区域会变黑。如需白底,可先用
ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height);填充背景再绘图 -
高 DPI 屏幕适配:若画布被 CSS 缩放(如 retina 屏),导出尺寸可能失真。确保
canvas.width/canvas.height是实际像素尺寸,而非 CSS 宽高
一键导出封装函数(实用版)
兼顾格式、质量、错误处理和清理:
function exportCanvas(canvas, options = {}) {
const {
type = 'image/png',
quality = 0.95,
filename = `canvas.${type.split('/')[1] || 'png'}`
} = options;
return new Promise((resolve, reject) => {
canvas.toBlob(
blob => {
if (!blob) return reject(new Error('Export failed: empty blob'));
const url = URL.createObjectURL(blob);
const a = Object.assign(document.createElement('a'), {
href: url,
download: filename
});
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
resolve(blob);
},
type,
type === 'image/jpeg' || type === 'image/webp' ? quality : undefined
);
});
}
// 使用示例:
// exportCanvas(myCanvas, { type: 'image/jpeg', quality: 0.8, filename: 'chart.jpg' });
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










