不使用html2canvas实现HTML div内容导出为png/jpg图片并下载的方案
实现方案
你的场景属于固定分层PNG素材叠加合成,不需要解析复杂DOM样式,直接用原生Canvas按堆叠顺序绘制选中的素材即可实现需求,完全不需要引入html2canvas库。
实现思路
- 先做预览交互:勾选复选框时显示对应部位的素材,取消勾选则隐藏,方便用户实时预览效果
- 监听表单提交事件,阻止默认跳转行为
- 创建Canvas画布,按层级从下到上的顺序绘制所有选中的素材
- 将绘制完成的Canvas转成指定格式的图片,触发浏览器自动下载
完整可运行代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>人脸生成器</title> <style> #pic { position: relative; /* 此处宽高替换为你实际素材的真实尺寸 */ width: 500px; height: 600px; } #pic img { position: absolute; top: 0; left: 0; display: none; width: 100%; height: 100%; } </style> </head> <body id="pageBody"> <form action="" id="form"> <label for="body">Body</label><input type="checkbox" name="body" id="body"> <label for="eyes">Eyes</label><input type="checkbox" name="eyes" id="eyes"> <label for="nose">Nose</label><input type="checkbox" name="nose" id="nose"> <label for="mouth">Mouth</label><input type="checkbox" name="mouth" id="mouth"> <label for="hat">Hat</label><input type="checkbox" name="hat" id="hat"> <input type="submit" value="submit"> </form> <br> <div id="pic"> <img id="bodyImg" src="imgs/body.png"/> <img id="eyesImg" src="imgs/eyes.png"/> <img id="mouthImg" src="imgs/mouth.png"/> <img id="noseImg" src="imgs/nose.png"/> <img id="hatImg" src="imgs/hat.png"/> </div> <script> // 复选框和预览效果绑定 const checkboxes = document.querySelectorAll('#form input[type="checkbox"]'); checkboxes.forEach(checkbox => { const targetImg = document.getElementById(`${checkbox.id}Img`); checkbox.addEventListener('change', () => { targetImg.style.display = checkbox.checked ? 'block' : 'none'; }) }) // 表单提交合成下载逻辑 document.getElementById('form').addEventListener('submit', async (e) => { e.preventDefault(); // 素材绘制顺序,越靠后层级越高,可根据实际需求调整顺序 const drawOrder = ['body', 'nose', 'eyes', 'mouth', 'hat']; const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // 画布尺寸和素材实际尺寸保持一致 canvas.width = 500; canvas.height = 600; // 按顺序绘制选中的素材 for (const part of drawOrder) { const isChecked = document.getElementById(part).checked; if (isChecked) { const img = document.getElementById(`${part}Img`); // 确保图片加载完成再绘制,避免出现空白 await new Promise((resolve) => { if (img.complete) return resolve(); img.onload = resolve; }) ctx.drawImage(img, 0, 0, canvas.width, canvas.height); } } // 触发下载 const downloadLink = document.createElement('a'); downloadLink.download = '自定义人脸.png'; // 如需导出jpg格式,替换为 canvas.toDataURL('image/jpeg', 0.9),第二个参数为图片质量0-1 downloadLink.href = canvas.toDataURL('image/png'); downloadLink.click(); }) </script> </body> </html>
注意事项
- 如果你的素材存在跨域情况,需要给所有img标签添加
crossorigin="anonymous"属性,同时素材所在的服务端需要配置CORS跨域规则 - 代码里的画布尺寸、下载文件名可根据自己的需求灵活修改
内容的提问来源于stack exchange,提问作者Cheetos
相关产品推荐
相关产品推荐

