web上的OffscreenCanvas-离屏canvas使用说明(离屏渲染)

OffscreenCanvas 是一个实验中的新特性(在最新版本的 Chrome 和 Firefox 上都可以通过实验室开关打开,Chrome 的开关是 chome://flags -> Experimental Web Platform features(离屏渲染chrome86已默认支持,不需要开启),本文的例程是在 Chrome 67 Canary 上进行验证,主要用于提升 Canvas 2D/3D 绘图的渲染性能和使用体验。

OffscreenCanvas和canvas都是渲染图形的对象。 不同的是canvas只能在window环境下使用,而OffscreenCanvas既可以在window环境下使用,也可以在web worker中使用,这让不影响浏览器主线程的离屏渲染成为可能。

跟 OffscreenCanvas 关系比较紧密的还有另外两个新的 API,ImageBitmapImageBitmapRenderingContext。

使用解析

OffscreenCanvas 目前主要用于两种不同的使用场景:

  • Transfer 模式:一种是在 Worker 线程创建一个 OffscreenCanvas 做后台渲染,然后再把渲染好的缓冲区 Transfer 回主线程显示;
  • Commit 模式:一种是主线程从当前 DOM 树中的 Canvas 元素产生一个 OffscreenCanvas,再把这个 OffscreenCanvas 发送给 Worker 线程进行渲染,渲染的结果直接 Commit 到浏览器的 Display Compositor 输出到当前窗口,相当于在 Worker 线程直接更新 Canvas 元素的内容;

一、Transfer模式

应用场景:Transfer 模式主要用于后台渲染,避免耗时的渲染任务会阻塞前台线程,导致应用无法及时响应用户的操作,比如一些 2D/3D 图表,图形可视化应用,地图应用等。

Transfer Demo 运行流程大致如下:

  1. 主线程启动 Worker 线程,并请求初始化;
  2. Worker 线程创建 OffscreenCanvas;
  3. Worker 线程获取 OffscreenCanvas 的 WebGL Context 并进行绘制;
  4. Worker 线程获取 OffscreenCanvas 的缓冲区(ImageBitmap),然后 Transfer 回主线程;
  5. 主线程将 Worker 线程回传的缓冲区分别绘制在两个不同的 Canvas 上,一个 Canvas 使用 CanvasRenderingContext2D,一个 Canvas 使用 ImageBitmapRenderingContext
  6. 3 ~ 5 重复运行;

1、渲染到canvas上的两种方式:

  • 方案一:ImageBitmap 可以被当做普通的 Image 绘制在一个 2D Canvas 上;
  • 方案二:可以通过 ImageBitmapRenderingContext Transfer 到一个 Bitmap Canvas;

2、ImageBitmap介绍

  • ImageBitmap 主要是用来封装一块 GPU 缓冲区,可以被 GPU 读写,并且实现了 Transferable 的接口(transferFromImageBitmap和transferToImageBitmap),可以在不同线程之间 Transfer。
  • 跟 ImageData 不一样,ImageBitmap 并没有提供 JavaScipt API 供 CPU 进行读写,这是因为使用 CPU 读写 GPU 缓冲区的成本非常高,需要拷贝到临时缓冲区进行读写然后再写回。这也是为什么规范的制定者没有扩展 ImageData,而是提供了一个新的 ImageBitmap 的缘故。

3、渲染的具体流程:

  • (1) 当我们使用 OffscreenCanvas,通过 2D/3D 进行绘制时==》我们有一块画板,上面有一些画纸,我们可以在画纸上作画
  • (2) 调用 OffscreenCanvas.transferToImageBitmap 获取 ImageBitmap 封装的缓冲区==》我们把当前绘画的画纸取下来;
function TransferBuffer() {
  let image_bitmap = canvas.transferToImageBitmap();
  postMessage({name:"TransferBuffer", buffer:image_bitmap},
    [image_bitmap]);
}
  • (3) 把 ImageBitmap 作为 Image 绘制在一个 2D Canvas(方案一)==》我们对已经绘制好的图画在新的画纸上进行临摹
function init() {
    g_bitmap_canvas = helper.GetCanvas("bitmap");
    g_2d_canvas = helper.GetCanvas("2d");
    g_render_worker = new Worker("./render_worker.js");
    g_render_worker.onmessage = function(msg) {

    if (msg.data.name === "TransferBuffer") {
        GetTransferBuffer(msg.data.buffer);
    }
  }
}

function GetTransferBuffer(buffer) {
    let context_2d = g_2d_canvas.getContext("2d");
    context_2d.clearRect(0, 0, g_2d_canvas.width, g_2d_canvas.height);
    context_2d.save();
    context_2d.translate(g_bitmap_canvas.width / 2, g_bitmap_canvas.height / 2);
    context_2d.rotate(g_angle * Math.PI / 180);
    context_2d.scale(0.5, 0.5);
    context_2d.translate(-g_bitmap_canvas.width / 2, -g_bitmap_canvas.height / 2);                  
    context_2d.drawImage(buffer, 0, 0);
    context_2d.restore();

    g_angle += 15;
    if (g_angle &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值