akira-cn / FE_You_dont_know

分享在前端开发中,你不知道的JavaScript、CSS和HTML趣味知识,增加你的知识面。
954 stars 53 forks source link

Canvas的4个渲染上下文 #16

Open akira-cn opened 5 years ago

akira-cn commented 5 years ago

做前端的同学应该都知道,Canvas是浏览器中很重要的一个绘图元素,使用它可以绘制2D图形或者3D图形,要绘制2D或3D图形时,需要获取不同的上下文,最常用的两个上下文是2d上下文webgl上下文

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d'); // 获取2d上下文
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgl'); // 获取webgl上下文

如上面代码所示,最常用的上下文是这两个,不过这里有些细节需要注意。

👉🏻 首先,一个canvas对象只能获取一种类型的上下文,以第一次调用getContext获取的上下文为准。

const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgl'); // 获取webgl上下文
const context2 = canvas.getContext('2d');

console.log(context); // WebGLRenderingContext
console.log(context2); // null

上面的代码,canvas对象已经获取过webgl上下文,再获取2d上下文,就会返回null。

👉🏻 getContext获取上下文有第二个参数,可以传配置项,webgl和2d上下文的配置项不同。

2d上下文可以配置的参数如下:

webgl上下文可配置的参数如下:

👉🏻 最新的chrome中还支持一个属性 desynchronized,它可以创建低延时渲染上下文

实际上,除了webgl和2d上下文外,canvas还支持另外两种上下文,分别是:

webgl2比webgl多了一些OpenGL ES 3.0实现的强大功能,它们不但性能更好而且使用更简单。所以如果你的绘图在高级浏览器上运行,可以使用webgl2代替webgl渲染。

如果你只是想要处理图片内容,你可以创建bitmaprenderer上下文,它提供transferFromImageBitmap()方法,可以将ImageBitmap的内容传入。

function loadImage(src) {
  const image = new Image();
  return new Promise((resolve) => {
    image.onload = function() {
      resolve(image);
    }
    image.src = src;
  });
}

(async function() {
  const image = await loadImage(url);
  const bitmap = createImageBitmap(image, 0, 0, 32, 32);
  const canvas = document.querySelector('canvas');
  const context = canvas.getContext('bitmaprenderer');
  context.transferFromImageBitmap(bitmap);
  ...
}());

👉🏻 因为bitmaprenderer是可以用于worker上下文中的,所以这是一种快速让位图数据在worker和主线程中通讯的方式。

以上是canvas的4个上下文,现在新的标准支持的canvas除了原有的canvas元素,还支持离屏canvas(OffscreenCanvas),使用这些上下文和BitmapImage能够高性能地完成很多复杂的渲染,后续我们的文章中有机会再一一讨论。

关于canvas的渲染上下文,你还有什么想法,欢迎在issue中讨论。

HypnosNova commented 2 years ago

还有webgpu上下文