OffscreenCanvas是纯JS API,不可通过HTML标签声明;必须用new OffscreenCanvas()或transferControlToOffscreen()创建,且传入Worker时须在postMessage第二参数中显式transfer,否则getContext返回null。

OffscreenCanvas 不是“用 HTML 做”的——它不通过 HTML 标签声明,也不能写在 .html 文件里靠浏览器自动解析。它是纯 JS API,必须用 JavaScript 创建。想在 HTML 页面里用 OffscreenCanvas,关键不是写什么标签,而是选对创建方式、避开兼容性雷区、别误把 DOM <canvas> 当成 OffscreenCanvas。
OffscreenCanvas 构造函数 vs transferControlToOffscreen()
现代浏览器(Chrome 69+、Edge 79+、Firefox 未完全支持)提供两种创建方式,但行为和限制完全不同:
-
new OffscreenCanvas(width, height):最直接,适合主线程或 Worker 中独立使用;但 Safari 完全不支持,且不能回传到 DOM 渲染 -
canvas.transferControlToOffscreen():必须先有一个已挂载的 DOM<canvas>元素,调用后该元素立刻失去绘制能力(getContext('2d')报错),控制权移交;优势是兼容性稍好,且能同步渲染到原 canvas(即“一边离屏画,一边主屏显”) - 错误做法:
document.createElement('canvas')得到的是普通 canvas,不是 OffscreenCanvas;即使不插入 DOM,它仍是主线程同步渲染对象,不享受离屏/Worker 能力
OffscreenCanvas.getContext('2d') 后无法访问 canvas.width/height
这是最容易踩的隐性坑:OffscreenCanvas 实例本身有 width 和 height 属性,但它的上下文 OffscreenCanvasRenderingContext2D 对象没有 canvas 引用,所以 ctx.canvas.width 会报 TypeError: Cannot read property 'width' of null。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 正确写法:始终从
offscreen实例读尺寸,例如offscreen.width,而不是ctx.canvas.width - 常见翻车场景:封装绘图函数时习惯写
ctx.canvas.width,一换 OffscreenCanvas 就崩 - 高 DPI 适配时尤其危险:
offscreen.width = 1024 * window.devicePixelRatio必须手动设,不能依赖 CSS 或父容器
OffscreenCanvas 传入 Web Worker 的 transfer 语法
Worker 中使用 OffscreenCanvas 是它最大价值所在,但传输过程有硬性约束:
立即学习“前端免费学习笔记(深入)”;
- 必须用
postMessage(data, transferList)的第二个参数显式传递,例如:worker.postMessage({ canvas: offscreen }, [offscreen]) - 漏写
[offscreen]就只是浅拷贝,Worker 收到的是空对象,getContext()返回null - 主线程调用
transferControlToOffscreen()后,原始 DOM<canvas>不再响应toDataURL()、toBlob()等方法,这些调用会静默失败 - Worker 内绘制完成后,不能直接“推送画面”,需转成
ImageBitmap(用createImageBitmap(offscreen))再 post 回主线程,由主线程drawImage(imageBitmap, ...)
真正难的不是创建 OffscreenCanvas,而是判断“该不该用”以及“哪一层该拆出去”。比如一个每帧都变的粒子系统,塞进 OffscreenCanvas 反而更慢;而一个带复杂滤镜的静态地图底图,提前画好再复用,帧耗能从 4ms 降到 0.3ms——差在是否理解“离屏”本质是缓存计算结果,不是换个地方画而已。


















