JavaScript 动态生成海报
三种在浏览器和 Node.js 中动态生成海报图片的实现方案
问题
如何使用 JavaScript 动态生成海报图片?
解答
方案一:DOM → Canvas → Image
将 DOM 节点绘制到 canvas 画布,再导出为图片。
绘制阶段
选择目标 DOM 节点,根据 nodeType 属性调用 canvas 对应的 API 进行绘制。
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 对于图片元素使用 drawImage
const img = document.querySelector('img');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// 对于文本使用 fillText
ctx.font = '16px Arial';
ctx.fillText('Hello World', 10, 50);
导出阶段
使用 canvas 的导出接口生成图片。
// 导出为 base64
const dataURL = canvas.toDataURL('image/png');
// 或获取图片数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
方案二:DOM → SVG → Canvas → Image
将 HTML 作为 SVG 的外联元素,利用 SVG 导出为图片。
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="600">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml">
${htmlContent}
</div>
</foreignObject>
</svg>
`;
const blob = new Blob([svg], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0);
const dataURL = canvas.toDataURL('image/png');
};
img.src = url;
方案三:Node.js 调用浏览器
在后端使用 Puppeteer 等库调用浏览器截图。
const puppeteer = require('puppeteer');
async function generatePoster() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent('<div>海报内容</div>');
await page.screenshot({
path: 'poster.png',
fullPage: true
});
await browser.close();
}
关键点
- 方案一适合简单场景,需手动处理各类 DOM 节点的绘制逻辑
- 方案二通过 SVG 的
foreignObject可以保留 HTML 样式,但存在浏览器兼容性问题 - 方案三在服务端生成,性能稳定,适合批量生成海报的场景
- Canvas 导出时注意跨域图片需设置
crossOrigin属性
目录