--- title: OffscreenCanvas slug: Web/API/OffscreenCanvas tags: - API - Canvas - Experimental - Interface - Reference translation_of: Web/API/OffscreenCanvas --- <div>{{APIRef("Canvas API")}} {{SeeCompatTable}}</div> <p><strong><code>OffscreenCanvas提供了一个可以脱离屏幕渲染的canvas对象。它在窗口环境和<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API">web worker</a>环境均有效。</code></strong></p> <h2 id="构造函数">构造函数</h2> <dl> <dt>{{domxref("OffscreenCanvas.OffscreenCanvas", "OffscreenCanvas()")}}</dt> <dd><code>OffscreenCanvas构造函数。创建一个新的</code><code>OffscreenCanvas对象。</code></dd> </dl> <h2 id="属性">属性</h2> <dl> <dt>{{domxref("OffscreenCanvas.height")}}</dt> <dd>offscreen canvas对象的高度。</dd> <dt>{{domxref("OffscreenCanvas.width")}}</dt> <dd>offscreen canvas对象的宽度。</dd> </dl> <h2 id="方法">方法</h2> <dl> <dt>{{domxref("OffscreenCanvas.getContext()")}}</dt> <dd>为offscreen canvas对象返回一个渲染画布。</dd> </dl> <dl> <dt>{{domxref("OffscreenCanvas.toBlob()")}}</dt> <dd>创建一个代表canvas中的图像的{{domxref("Blob")}}对象。</dd> </dl> <dl> <dt>{{domxref("OffscreenCanvas.transferToImageBitmap()")}}</dt> <dd>从<code>OffscreenCanvas最近渲染的图像</code>创建一个 {{domxref("ImageBitmap")}} 对象。</dd> </dl> <h2 id="例子">例子</h2> <h3 id="同步显示OffscreenCanvas中的帧">同步显示<code>OffscreenCanvas中的帧</code></h3> <p>一种方式是使用<code>OffscreenCanvas</code> API,也就是用已经包含<code>OffscreenCanvas</code>对象的{{domxref("RenderingContext")}} 来生成新的帧。 每次一个新的帧在画布中完成渲染,{{domxref("OffscreenCanvas.transferToImageBitmap", "transferToImageBitmap()")}} 方法都会被调用来保存最近渲染的图像。该方法返回一个{{domxref("ImageBitmap")}}对象,该对象可以被用在各种Web APIs中,也可以用在下一个canvas中,并且不需要转换备份。</p> <p>为了显示<code>ImageBitmap</code>,你可以用{{domxref("ImageBitmapRenderingContext")}}上下文,通过一个canvas(可见的)元素调用<code>canvas.getContext("bitmaprenderer")</code>方法来创建它。该上下文只提供用<code>ImageBitmap</code>替换canvas的内容的功能。调用{{domxref("ImageBitmapRenderingContext.transferFromImageBitmap()")}} 以前的渲染结果并且通过OffscreenCanvas保存<code>ImageBitmap</code>,会在canvas里显示<code>ImageBitmap</code>并且转换其所有权到canvas。 一个单独的OffscreenCanvas可以将帧转换到任意数量的其他<code>ImageBitmapRenderingContext</code>对象。</p> <p>提供两个 {{HTMLElement("canvas")}} 元素</p> <pre class="brush: html notranslate"><canvas id="one"></canvas> <canvas id="two"></canvas></pre> <p>下面的代码会用<code>OffscreenCanva提供渲染结果,就像上面描述的一样。</code></p> <pre class="brush: js notranslate">var one = document.getElementById("one").getContext("bitmaprenderer"); var two = document.getElementById("two").getContext("bitmaprenderer"); var offscreen = new OffscreenCanvas(256, 256); var gl = offscreen.getContext('webgl'); // ... some drawing for the first canvas using the gl context ... // Commit rendering to the first canvas var bitmapOne = offscreen.transferToImageBitmap(); one.transferFromImageBitmap(bitmapOne); // ... some more drawing for the second canvas using the gl context ... // Commit rendering to the second canvas var bitmapTwo = offscreen.transferToImageBitmap(); two.transferFromImageBitmap(bitmapTwo); </pre> <h3 id="异步显示OffscreenCanvas生成的帧"> 异步显示<code>OffscreenCanvas生成的帧</code></h3> <p><code>另一种使用 OffscreenCanvas</code> API的方式, 是在一个{{HTMLElement("canvas")}}元素上调用{{domxref("HTMLCanvasElement.transferControlToOffscreen", "transferControlToOffscreen()")}}, 也可以在<a href="/en-US/docs/Web/API/Web_Workers_API">worker</a>或主线程,上调用,这将从主线程的{{domxref("HTMLCanvasElement")}}对象返回一个<code>OffscreenCanvas对象。调用</code>{{domxref("OffscreenCanvas.getContext", "getContext()")}} 会从这个<code>OffscreenCanvas获取一个<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/RenderingContext">RenderingContext </a>。</code></p> <p>main.js (主线程代码):</p> <pre class="brush: js notranslate">var htmlCanvas = document.getElementById("canvas"); var offscreen = htmlCanvas.transferControlToOffscreen(); var worker = new Worker("offscreencanvas.js"); worker.postMessage({canvas: offscreen}, [offscreen]); </pre> <p>offscreencanvas.js (web work代码):</p> <pre class="brush: js notranslate">onmessage = function(evt) { var canvas = evt.data.canvas. var gl = canvas.getContext("webgl"); // ... some drawing using the gl context ... // Push frames back to the original HTMLCanvasElement gl.commit(); }; </pre> <p>也可以在 worker 中使用 requestAnimationFrame</p> <pre class="brush: js notranslate">onmessage = function(evt) { const canvas = evt.data.canvas; const gl = canvas.getContext("webgl"); function render(time) { // ... some drawing using the gl context ... requestAnimationFrame(render); } requestAnimationFrame(render); };</pre> <h2 id="规范">规范</h2> <table class="standard-table"> <tbody> <tr> <th scope="col">规范</th> <th scope="col">状态</th> <th scope="col">备注</th> </tr> <tr> <td>{{SpecName('HTML WHATWG', "scripting.html#the-offscreencanvas-interface", "OffscreenCanvas")}}</td> <td>{{Spec2('HTML WHATWG')}}</td> <td></td> </tr> </tbody> </table> <h2 id="浏览器兼容性">浏览器兼容性</h2> <div> <p>{{Compat("api.OffscreenCanvas")}}</p> </div> <h2 id="另请参见">另请参见</h2> <ul> <li><a href="https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/">WebGL Off the Main Thread – Mozilla Hacks</a></li> <li>{{domxref("CanvasRenderingContext2D")}}</li> <li>{{domxref("ImageBitmap")}}</li> <li>{{domxref("ImageBitmapRenderingContext")}}</li> <li>{{domxref("HTMLCanvasElement.transferControlToOffscreen()")}}</li> <li>{{domxref("WebGLRenderingContext.commit()")}}</li> </ul> <div id="gtx-anchor" style="position: absolute; left: 78px; top: 2140px; width: 183px; height: 20px;"></div> <div class="jfk-bubble gtx-bubble" style=""> <div class="jfk-bubble-content-id" id="bubble-3"> <div id="gtx-host" style="max-width: 400px;"></div> </div> <div class="jfk-bubble-closebtn-id jfk-bubble-closebtn"></div> <div class="jfk-bubble-arrow-id jfk-bubble-arrow jfk-bubble-arrowdown" style="left: 71.5px;"> <div class="jfk-bubble-arrowimplbefore"></div> <div class="jfk-bubble-arrowimplafter"></div> </div> </div>