前端html2canvas使用場景的詳細教程
前言
html2canvas 是前端常用的 “DOM 轉(zhuǎn)圖片” 庫,核心是將頁面 DOM 節(jié)點渲染為 Canvas,再轉(zhuǎn)為圖片(Base64 或 Blob)。以下是 9 種核心使用場景的詳細教程,包含代碼示例、參數(shù)配置、問題解決,覆蓋日常開發(fā)需求。
一、基礎(chǔ)使用:將指定 DOM 轉(zhuǎn)為 Base64 圖片
適用于簡單場景(如生成證書、截圖分享),無需復(fù)雜配置。
1. 安裝與引入
# npm 安裝 npm install html2canvas --save
javascript
// 模塊化項目引入(Vue/React/Angular) import html2canvas from 'html2canvas'; // 非模塊化項目(直接引入 CDN) <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
2. 核心代碼
html
<!-- 目標 DOM:需要轉(zhuǎn)為圖片的容器 --> <div id="targetDom" style="width: 300px; height: 200px; background: #f5f5f5; padding: 20px;"> <h2>基礎(chǔ)截圖示例</h2> <p>這是要轉(zhuǎn)為圖片的內(nèi)容</p> </div> <!-- 圖片預(yù)覽容器 --> <img id="previewImg" style="margin-top: 20px; max-width: 100%;" />
javascript
// 觸發(fā)截圖(如點擊按鈕后)
document.querySelector('#btn').addEventListener('click', async () => {
// 1. 獲取目標 DOM
const targetDom = document.getElementById('targetDom');
// 2. 調(diào)用 html2canvas 生成 Canvas
const canvas = await html2canvas(targetDom, {
scale: 2, // 2倍縮放,避免圖片模糊(關(guān)鍵參數(shù))
useCORS: true, // 允許跨域圖片(如網(wǎng)絡(luò)圖片)
logging: false, // 關(guān)閉控制臺日志
backgroundColor: null // 保留 DOM 原有背景(默認白色)
});
// 3. Canvas 轉(zhuǎn)為 Base64 圖片(支持 jpeg/png)
const base64Img = canvas.toDataURL('image/jpeg', 1.0); // 1.0 表示質(zhì)量(0-1)
// 4. 預(yù)覽圖片
document.getElementById('previewImg').src = base64Img;
// 5. (可選)下載圖片
const link = document.createElement('a');
link.href = base64Img;
link.download = '基礎(chǔ)截圖.jpg';
link.click();
});
二、進階場景:處理跨域圖片
當(dāng) DOM 中包含網(wǎng)絡(luò)圖片(如 https://xxx.com/xxx.jpg),易出現(xiàn) “圖片空白” 問題,需配置跨域參數(shù)。
關(guān)鍵配置
- 前端配置:
useCORS: true+allowTaint: true(允許跨域圖片污染 Canvas); - 后端配置:圖片服務(wù)器需返回
Access-Control-Allow-Origin: *(或當(dāng)前域名),否則跨域圖片仍會空白。
完整代碼
javascript
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('跨域域名', '同源代理域名');
}
});
}
});
三、復(fù)雜場景:固定寬高 + 滾動內(nèi)容截圖
適用于 “長列表截圖”(如表格、聊天記錄),需固定截圖寬高,同時包含滾動區(qū)域的所有內(nèi)容。
核心思路
- 先保存目標 DOM 的原始樣式(
overflow/height); - 臨時修改為
overflow: visible+ 自適應(yīng)高度(確保所有內(nèi)容展開); - 截圖完成后恢復(fù)原始樣式。
完整代碼
javascript
async function captureScrollContent() {
const targetDom = document.getElementById('targetDom');
// 1. 保存原始樣式
const originalStyle = {
overflow: targetDom.style.overflow,
height: targetDom.style.height
};
try {
// 2. 臨時修改樣式:展開所有滾動內(nèi)容
targetDom.style.overflow = 'visible';
targetDom.style.height = 'auto'; // 自適應(yīng)高度,顯示所有內(nèi)容
// 3. 截圖(固定寬高,避免內(nèi)容變形)
const canvas = await html2canvas(targetDom, {
scale: 2,
useCORS: true,
logging: false,
windowWidth: targetDom.offsetWidth, // 固定截圖寬度
windowHeight: targetDom.offsetHeight // 固定截圖高度(此時已包含所有內(nèi)容)
});
// 4. 轉(zhuǎn)為圖片并下載
const base64Img = canvas.toDataURL('image/png', 1.0);
const link = document.createElement('a');
link.href = base64Img;
link.download = '長列表截圖.png';
link.click();
} finally {
// 5. 恢復(fù)原始樣式(無論成功失敗都要恢復(fù))
targetDom.style.overflow = originalStyle.overflow;
targetDom.style.height = originalStyle.height;
}
}
// 調(diào)用
captureScrollContent();
四、Vue 項目:組件內(nèi) DOM 截圖(含響應(yīng)式數(shù)據(jù))
Vue 中需注意 “DOM 渲染時機”—— 確保數(shù)據(jù)更新后(如接口請求完成)再截圖,避免內(nèi)容空白。
核心注意點
- 用
this.$nextTick()確保 DOM 已更新; - 若用
v-for渲染列表,需等待列表渲染完成后再截圖。
完整代碼(Vue 3 示例)
vue
<template>
<div>
<!-- 目標 DOM:包含響應(yīng)式數(shù)據(jù) -->
<div ref="certDom" class="cert-container">
<h2>{{ userName }} 的證書</h2>
<p>項目:{{ projectName }}</p>
<p>時間:{{ date }}</p>
</div>
<button @click="generateCert">生成證書</button>
<img :src="previewImg" alt="證書預(yù)覽" style="max-width: 100%; margin-top: 20px;" />
</div>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import html2canvas from 'html2canvas';
// 響應(yīng)式數(shù)據(jù)
const userName = ref('');
const projectName = ref('');
const date = ref('2025-01-01');
const previewImg = ref('');
const certDom = ref(null); // 目標 DOM 引用
// 接口請求:獲取用戶數(shù)據(jù)
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. 先獲取數(shù)據(jù),確保 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. 預(yù)覽并下載
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 項目:函數(shù)組件截圖(含 Hooks)
React 中需用 useRef 獲取 DOM 節(jié)點,用 useEffect 處理異步渲染時機。
完整代碼(React 18 示例)
jsx
import { useRef, useState } from 'react';
import html2canvas from 'html2canvas';
const ScreenshotComponent = () => {
// 1. 獲取目標 DOM 引用
const targetRef = useRef(null);
// 2. 預(yù)覽圖片狀態(tài)
const [previewImg, setPreviewImg] = useState('');
// 截圖函數(shù)
const captureDom = async () => {
if (!targetRef.current) return;
// 3. 調(diào)用 html2canvas
const canvas = await html2canvas(targetRef.current, {
scale: 2,
useCORS: true,
logging: false
});
// 4. 轉(zhuǎn)為圖片
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>當(dāng)前時間:{new Date().toLocaleString()}</p>
</div>
<button onClick={captureDom} style={{ margin: 20 }}>生成截圖</button>
{previewImg && <img src={previewImg} alt="預(yù)覽" style={{ maxWidth: '100%' }} />}
</div>
);
};
export default ScreenshotComponent;
六、特殊場景:隱藏 DOM 截圖(不顯示在頁面)
適用于 “后臺生成圖片”(如生成后直接下載,無需在頁面顯示 DOM),需臨時將 DOM 渲染到頁面外。
核心思路
- 目標 DOM 初始樣式設(shè)為
position: absolute; left: -9999px; top: -9999px;(隱藏在視口外); - 截圖完成后可刪除該 DOM(可選)。
完整代碼
html
<!-- 隱藏的目標 DOM:在視口外渲染 --> <div id="hiddenDom" style="position: absolute; left: -9999px; top: -9999px; width: 500px; height: 300px; background: #fff; padding: 30px;"> <h2>隱藏 DOM 生成的圖片</h2> <p>用戶:張三</p> <p>等級:VIP</p> </div> <button id="generateBtn">生成隱藏圖片</button>
javascript
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();
});
七、性能優(yōu)化:批量截圖 + 避免重復(fù)渲染
當(dāng)需要批量生成圖片(如多條數(shù)據(jù)生成證書),需控制截圖順序,避免同時渲染導(dǎo)致瀏覽器卡頓。
核心思路
- 用
async/await按順序截圖(一條完成后再截下一條); - 截圖前判斷是否已生成,避免重復(fù)操作。
完整代碼
javascript
// 批量數(shù)據(jù)(如多條證書信息)
const certList = [
{ id: 1, userName: '張三', project: '前端開發(fā)' },
{ id: 2, userName: '李四', project: '后端開發(fā)' },
{ id: 3, userName: '王五', project: 'UI設(shè)計' }
];
// 批量截圖函數(shù)
async function batchCapture() {
for (const cert of certList) {
// 1. 動態(tài)創(chuàng)建目標 DOM(每條數(shù)據(jù)一個 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. 截圖(按順序執(zhí)行)
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(避免內(nèi)存占用)
document.body.removeChild(tempDom);
// (可選)延遲 500ms,避免瀏覽器卡頓
await new Promise(resolve => setTimeout(resolve, 500));
}
}
}
// 調(diào)用批量截圖
batchCapture();
八、問題解決:常見報錯與優(yōu)化方案
1. 圖片模糊
- 原因:Canvas 默認縮放為 1,屏幕 DPI 過高(如 Retina 屏)導(dǎo)致模糊;
- 解決:設(shè)置
scale: 2或scale: window.devicePixelRatio(自適應(yīng)屏幕 DPI)。
javascript
const canvas = await html2canvas(targetDom, {
scale: window.devicePixelRatio, // 自適應(yīng)屏幕縮放
useCORS: true
});
2. 跨域圖片空白
- 原因:圖片服務(wù)器未配置 CORS,或未開啟
useCORS: true; - 解決:
后端添加
Access-Control-Allow-Origin響應(yīng)頭;前端配置
useCORS: true+allowTaint: true;備選方案:用同源代理服務(wù)器轉(zhuǎn)發(fā)圖片(如 Nginx 代理)。
3. DOM 內(nèi)容未完全渲染(如接口數(shù)據(jù)空白)
- 原因:截圖時機過早,DOM 尚未更新(如接口請求未完成);
- 解決:
- Vue:用
this.$nextTick()等待 DOM 渲染; - React:用
useEffect或await等待數(shù)據(jù)加載; - 原生 JS:在接口
then回調(diào)中執(zhí)行截圖。
- Vue:用
4. 大 DOM 截圖卡頓
- 原因:DOM 節(jié)點過多(如長列表、復(fù)雜表格),渲染耗時;
- 解決:
簡化 DOM(移除截圖無關(guān)的節(jié)點,如隱藏按鈕、多余注釋);
分批截圖(避免一次性渲染大量節(jié)點);
關(guān)閉日志:
logging: false(減少控制臺輸出耗時)。
九、高級場景:Canvas 轉(zhuǎn) Blob 上傳服務(wù)器
當(dāng)需要將生成的圖片上傳到后端(而非本地下載),需將 Canvas 轉(zhuǎn)為 Blob 格式(比 Base64 更節(jié)省帶寬)。
完整代碼
javascript
async function captureAndUpload() {
const targetDom = document.getElementById('targetDom');
const canvas = await html2canvas(targetDom, {
scale: 2,
useCORS: true,
logging: false
});
// 1. Canvas 轉(zhuǎn)為 Blob(支持指定格式和質(zhì)量)
canvas.toBlob(async (blob) => {
// 2. 構(gòu)建 FormData(用于上傳)
const formData = new FormData();
formData.append('image', blob, '上傳圖片.jpg'); // 第三個參數(shù)是文件名
formData.append('userId', '123'); // 其他參數(shù)(如用戶ID)
// 3. 上傳到服務(wù)器
try {
const res = await fetch('/api/upload-image', {
method: 'POST',
body: formData,
// 注意:FormData 上傳無需設(shè)置 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 表示圖片質(zhì)量(0-1,值越高質(zhì)量越好)
}
// 調(diào)用
captureAndUpload();總結(jié)
到此這篇關(guān)于前端html2canvas使用場景的文章就介紹到這了,更多相關(guān)前端html2canvas使用場景內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析arp病毒背后利用的Javascript技術(shù)附解密方法
解析arp病毒背后利用的Javascript技術(shù)附解密方法...2007-08-08
javascript 動態(tài)修改css樣式方法匯總(四種方法)
為了達到某種特殊的效果我們需要用Javascript動態(tài)的去更改某一個標簽的Css屬性,如何動態(tài)修改css樣式呢?面對這個問題,小編帶領(lǐng)大家來解決javascript動態(tài)修改css樣式,小伙伴們都快來學(xué)習(xí)吧2015-08-08
JavaScript 閉包:函數(shù)背后的“背包”(一文詳解)
文章詳細解釋了JavaScript閉包的概念及其作用,包括數(shù)據(jù)封裝、函數(shù)柯里化和異步回調(diào)中的的狀態(tài)保持,并通過實例展示了閉閉如何工作以及如何避免潛在的內(nèi)存泄漏問題,感興趣的朋友一起看看吧2026-05-05
bootstrap table實現(xiàn)合并單元格效果
這篇文章主要為大家詳細介紹了bootstrap table實現(xiàn)合并單元格效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12

