不能直接在worker中截图dom生成海报,必须由主线程完成初始高保真渲染(含字体、css、dpr适配),再移交像素数据给worker做离线增强处理。

不能直接在 Worker 中“截图 DOM”生成海报级图表,OffscreenCanvas 本身没有 HTML 解析或样式计算能力。真正的高分海报图表必须由主线程完成初始渲染(含字体、CSS、响应式布局),再把像素数据安全移交 Worker 做离线增强处理——这才是兼顾质量、性能与兼容性的可行路径。
主线程:先渲染出高保真快照
海报质量的上限,取决于这一步是否完整还原了设计稿:
- 用 dom-to-image(比 html2canvas 更准)将目标图表容器转为 canvas,它能更好处理 CSS transforms、font-face 加载、SVG 内联样式
- 务必等待所有字体加载完成:
document.fonts.load('bold 16px "PingFang SC"')+await document.fonts.ready - 适配设备像素比(dpr):显式设置 canvas.width/height = rect.width × dpr,并用
ctx.scale(dpr, dpr)绘制,避免模糊 - 图片资源需预加载并设
crossOrigin="anonymous";跨域图建议由主线程 fetch → arrayBuffer → createImageBitmap 后再传入
Worker 线程:专注像素级增强与合成
拿到 ImageBitmap 后,Worker 才真正开始高效工作,不卡 UI、不触发重排:
- 创建 OffscreenCanvas 并设定精确尺寸(如 1200×1800),不能依赖 new OffscreenCanvas() 自动推导,必须显式传宽高
- 用
ctx.drawImage(bitmap, 0, 0)贴底图,再叠加水印、二维码、标题文字(注意:fillText 在部分浏览器 Worker 中静默失败,推荐用 SVG 文字转 path 后用ctx.fill(path)或预渲染文字到小 canvas 再 transfer) - 支持滤镜增强:用
ctx.filter = 'contrast(1.2) brightness(1.05)',或手动遍历ctx.getImageData()做色阶调整(需 transferable ArrayBuffer) - 导出优先走
offscreen.convertToBlob({ type: 'image/png', quality: 0.95 });若失败(如 Safari),降级为toDataURL()
主线程接收:零拷贝渲染与内存管理
Worker 返回的不是 base64 字符串,而是可直接绘制的二进制资源:
- 收到 blob 后立即调用
URL.createObjectURL(blob),赋给<img>或插入 canvas:mainCtx.drawImage(img, 0, 0) - 每次生成新海报前,调用
URL.revokeObjectURL(oldUrl)释放旧引用,防止内存泄漏 - 若需下载,直接用
const a = document.createElement('a'); a.href = url; a.download = 'poster.png'; a.click(); - 避免在高频操作中反复创建/销毁 Worker,建议复用实例并用 message type 区分任务(如 'render' / 'add-qrcode')
整个流程不依赖第三方 CDN 渲染服务,全部运行在用户本地,既保障隐私又提升首屏速度。关键不在“能不能多线程”,而在于把对 DOM 和样式的强依赖留在主线程,把纯计算和像素操作交给 Worker —— 分工明确,海报才真正高清、稳定、可扩展。











