html2canvas 是前端常用的'DOM 转图片'库,核心是将页面 DOM 节点渲染为 Canvas,再转为图片(Base64 或 Blob)。以下是 9 种核心使用场景的详细教程,包含代码示例、参数配置、问题解决,覆盖日常开发需求。
一、基础使用:将指定 DOM 转为 Base64 图片
适用于简单场景(如生成证书、截图分享),无需复杂配置。
1. 安装与引入
# npm 安装
npm install html2canvas --save
html2canvas ;
html2canvas 库在 front-end 开发的 9 种核心应用场景,涵盖基础 DOM 转 Base64 图片、跨域图片处理、滚动长列表截图、Vue 及 React 组件集成、隐藏 DOM 生成、批量截图优化、常见报错解决以及 Canvas 转 Blob 上传服务器。包含代码示例与参数配置,帮助开发者实现高质量页面截图功能。
html2canvas 是前端常用的'DOM 转图片'库,核心是将页面 DOM 节点渲染为 Canvas,再转为图片(Base64 或 Blob)。以下是 9 种核心使用场景的详细教程,包含代码示例、参数配置、问题解决,覆盖日常开发需求。
适用于简单场景(如生成证书、截图分享),无需复杂配置。
# npm 安装
npm install html2canvas --save
html2canvas ;
<!-- 目标 DOM:需要转为图片的容器 -->
<div id="targetDom">
<h2>基础截图示例</h2>
<p>这是要转为图片的内容</p>
</div>
<!-- 图片预览容器 -->
<img id="previewImg" />
// 触发截图(如点击按钮后)
document.querySelector('#btn').addEventListener('click', async () => {
// 1. 获取目标 DOM
const targetDom = document.getElementById('targetDom');
// 2. 调用 html2canvas 生成 Canvas
const canvas = await html2canvas(targetDom, {
scale: 2, // 2 倍缩放,避免图片模糊(关键参数)
useCORS: true, // 允许跨域图片(如网络图片)
logging: false, // 关闭控制台日志
backgroundColor: null // 保留 DOM 原有背景(默认白色)
});
// 3. Canvas 转为 Base64 图片(支持 jpeg/png)
const base64Img = canvas.toDataURL('image/jpeg', 1.0); // 1.0 表示质量(0-1)
// 4. 预览图片
document.getElementById('previewImg').src = base64Img;
// 5. (可选)下载图片
const link = document.createElement('a');
link.href = base64Img;
link.download = '基础截图.jpg';
link.click();
});
当 DOM 中包含网络图片(如 https://xxx.com/xxx.jpg),易出现'图片空白'问题,需配置跨域参数。
useCORS: true + allowTaint: true(允许跨域图片污染 Canvas);Access-Control-Allow-Origin: *(或当前域名),否则跨域图片仍会空白。const canvas = await html2canvas(targetDom, {
scale: 2,
useCORS: true, // 允许加载跨域图片
allowTaint: true, // 允许 Canvas 被跨域图片污染(否则图片会被过滤)
logging: false, // (可选)处理跨域图片加载失败的情况
onclone: (clonedDoc) => {
// clonedDoc 是 DOM 克隆体,可在此修改图片地址
const imgs = clonedDoc.querySelectorAll('img');
imgs.forEach(img => {
// 替换图片为同源地址(若后端未配置 CORS 时的备选方案)
if (img.src.includes('跨域域名')) {
img.src = img.src.replace('跨域域名', '同源代理域名');
}
});
}
});
适用于'长列表截图'(如表格、聊天记录),需固定截图宽高,同时包含滚动区域的所有内容。
overflow/height);overflow: visible + 自适应高度(确保所有内容展开);async function captureScrollContent() {
const targetDom = document.getElementById('targetDom');
// 1. 保存原始样式
const originalStyle = {
overflow: targetDom.style.overflow,
height: targetDom.style.height
};
try {
// 2. 临时修改样式:展开所有滚动内容
targetDom.style.overflow = 'visible';
targetDom.style.height = 'auto'; // 自适应高度,显示所有内容
// 3. 截图(固定宽高,避免内容变形)
const canvas = await html2canvas(targetDom, {
scale: 2,
useCORS: true,
logging: false,
windowWidth: targetDom.offsetWidth, // 固定截图宽度
windowHeight: targetDom.offsetHeight // 固定截图高度(此时已包含所有内容)
});
// 4. 转为图片并下载
const base64Img = canvas.toDataURL('image/png', 1.0);
const link = document.createElement('a');
link.href = base64Img;
link.download = '长列表截图.png';
link.click();
} finally {
// 5. 恢复原始样式(无论成功失败都要恢复)
targetDom.style.overflow = originalStyle.overflow;
targetDom.style.height = originalStyle.height;
}
}
// 调用 captureScrollContent();
Vue 中需注意'DOM 渲染时机'—— 确保数据更新后(如接口请求完成)再截图,避免内容空白。
this.$nextTick() 确保 DOM 已更新;v-for 渲染列表,需等待列表渲染完成后再截图。<template>
<div>
<!-- 目标 DOM:包含响应式数据 -->
<div ref="certDom" class="cert-container">
<h2>{{ userName }} 的证书</h2>
<p>项目:{{ projectName }}</p>
<p>时间:{{ date }}</p>
</div>
<button @click="generateCert">生成证书</button>
<img :src="previewImg" alt="证书预览" />
</div>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import html2canvas from 'html2canvas';
// 响应式数据
const userName = ref('');
const projectName = ref('');
const date = ref('2025-01-01');
const previewImg = ref('');
const certDom = ref(null); // 目标 DOM 引用
// 接口请求:获取用户数据
const fetchUserInfo = async () => {
const res = await fetch('/api/user');
const data = await res.json();
userName.value = data.userName;
projectName.value = data.projectName;
};
// 生成证书(截图)
const generateCert = async () => {
// 1. 先获取数据,确保 DOM 已更新
await fetchUserInfo();
// 2. 等待 Vue DOM 渲染完成
await nextTick();
// 3. 截图(certDom.value 是目标 DOM)
const canvas = await html2canvas(certDom.value, {
scale: 2,
useCORS: true,
backgroundColor: '#fff'
});
// 4. 预览并下载
previewImg.value = canvas.toDataURL('image/jpeg', 1.0);
const link = document.createElement('a');
link.href = previewImg.value;
link.download = `${userName.value}的证书.jpg`;
link.click();
};
</script>
<style scoped>
.cert-container {
width: 500px;
height: 700px;
background: url('@/assets/cert-bg.jpg') no-repeat center;
background-size: 100% 100%;
padding: 50px;
box-sizing: border-box;
}
</style>
React 中需用 useRef 获取 DOM 节点,用 useEffect 处理异步渲染时机。
import { useRef, useState } from 'react';
import html2canvas from 'html2canvas';
const ScreenshotComponent = () => {
// 1. 获取目标 DOM 引用
const targetRef = useRef(null);
// 2. 预览图片状态
const [previewImg, setPreviewImg] = useState('');
// 截图函数
const captureDom = async () => {
if (!targetRef.current) return;
// 3. 调用 html2canvas
const canvas = await html2canvas(targetRef.current, {
scale: 2,
useCORS: true,
logging: false
});
// 4. 转为图片
const base64 = canvas.toDataURL('image/png', 1.0);
setPreviewImg(base64);
// 5. 下载图片
const link = document.createElement('a');
link.href = base64;
link.download = 'react 截图.png';
link.click();
};
return (
<div style={{ padding: 20 }}>
{/* 目标 DOM:用 ref 绑定 */}
<div ref={targetRef} style={{ width: 400, height: 300, background: '#e8f4f8', padding: 20 }}>
<h3>React 截图示例</h3>
<p>当前时间:{new Date().toLocaleString()}</p>
</div>
<button onClick={captureDom} style={{ margin: 20 }}>生成截图</button>
{previewImg && <img src={previewImg} alt="预览" style={{ maxWidth: '100%' }} />}
</div>
);
};
export default ScreenshotComponent;
适用于'后台生成图片'(如生成后直接下载,无需在页面显示 DOM),需临时将 DOM 渲染到页面外。
position: absolute; left: -9999px; top: -9999px;(隐藏在视口外);<!-- 隐藏的目标 DOM:在视口外渲染 -->
<div id="hiddenDom">
<h2>隐藏 DOM 生成的图片</h2>
<p>用户:张三</p>
<p>等级:VIP</p>
</div>
<button id="generateBtn">生成隐藏图片</button>
document.getElementById('generateBtn').addEventListener('click', async () => {
const hiddenDom = document.getElementById('hiddenDom');
// 截图(与正常 DOM 一致)
const canvas = await html2canvas(hiddenDom, {
scale: 2,
useCORS: true,
logging: false
});
// 下载图片
const base64 = canvas.toDataURL('image/jpeg', 1.0);
const link = document.createElement('a');
link.href = base64;
link.download = '隐藏 DOM 图片.jpg';
link.click();
// (可选)截图后删除隐藏 DOM
// hiddenDom.remove();
});
当需要批量生成图片(如多条数据生成证书),需控制截图顺序,避免同时渲染导致浏览器卡顿。
async/await 按顺序截图(一条完成后再截下一条);// 批量数据(如多条证书信息)
const certList = [
{ id: 1, userName: '张三', project: '前端开发' },
{ id: 2, userName: '李四', project: '后端开发' },
{ id: 3, userName: '王五', project: 'UI 设计' }
];
// 批量截图函数
async function batchCapture() {
for (const cert of certList) {
// 1. 动态创建目标 DOM(每条数据一个 DOM)
const tempDom = document.createElement('div');
tempDom.style.width = '500px';
tempDom.style.height = '700px';
tempDom.style.background = '#fff';
tempDom.style.padding = '50px';
tempDom.style.position = 'absolute';
tempDom.style.left = '-9999px'; // 隐藏在视口外
tempDom.innerHTML = `
<h2>${cert.userName} 的证书</h2>
<p>项目:${cert.project}</p>
<p>日期:2025-01-01</p>
`;
document.body.appendChild(tempDom);
try {
// 2. 截图(按顺序执行)
const canvas = await html2canvas(tempDom, {
scale: 2,
useCORS: true,
logging: false
});
// 3. 下载图片
const base64 = canvas.toDataURL('image/jpeg', 1.0);
const link = document.createElement('a');
link.href = base64;
link.download = `${cert.userName}的证书.jpg`;
link.click();
} finally {
// 4. 移除临时 DOM(避免内存占用)
document.body.removeChild(tempDom);
// (可选)延迟 500ms,避免浏览器卡顿
await new Promise(resolve => setTimeout(resolve, 500));
}
}
}
// 调用批量截图
batchCapture();
scale: 2 或 scale: window.devicePixelRatio(自适应屏幕 DPI)。const canvas = await html2canvas(targetDom, {
scale: window.devicePixelRatio, // 自适应屏幕缩放
useCORS: true
});
useCORS: true;Access-Control-Allow-Origin 响应头;useCORS: true + allowTaint: true;this.$nextTick() 等待 DOM 渲染;useEffect 或 await 等待数据加载;then 回调中执行截图。logging: false(减少控制台输出耗时)。当需要将生成的图片上传到后端(而非本地下载),需将 Canvas 转为 Blob 格式(比 Base64 更节省带宽)。
async function captureAndUpload() {
const targetDom = document.getElementById('targetDom');
const canvas = await html2canvas(targetDom, {
scale: 2,
useCORS: true,
logging: false
});
// 1. Canvas 转为 Blob(支持指定格式和质量)
canvas.toBlob(async (blob) => {
// 2. 构建 FormData(用于上传)
const formData = new FormData();
formData.append('image', blob, '上传图片.jpg'); // 第三个参数是文件名
formData.append('userId', '123'); // 其他参数(如用户 ID)
// 3. 上传到服务器
try {
const res = await fetch('/api/upload-image', {
method: 'POST',
body: formData, // 注意:FormData 上传无需设置 Content-Type,浏览器会自动处理
});
const data = await res.json();
if (data.success) {
alert('图片上传成功!');
console.log('图片地址:', data.imageUrl);
}
} catch (err) {
console.error('上传失败:', err);
}
}, 'image/jpeg', 0.8); // 0.8 表示图片质量(0-1,值越高质量越好)
}
// 调用 captureAndUpload();

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online