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