做前端的同学应该都知道,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上下文可以配置的参数如下:
alpha: boolean值,表明canvas包含一个alpha通道. 如果设置为false, 浏览器将认为canvas背景总是不透明的, 这样可以加速绘制透明的内容和图片.
webgl上下文可配置的参数如下:
alpha: boolean值,表明canvas包含一个alpha缓冲区,默认true。
antialias: boolean值,表明是否开启抗锯齿,默认true。
depth: boolean值,表明绘制缓冲区包含一个深度至少为16位的缓冲区,默认true。
failIfMajorPerformanceCaveat: boolean值,表明在一个系统性能低的环境是否创建该上下文的,默认false。
powerPreference: 指示浏览器在运行WebGL上下文时使用相应的GPU电源配置。可能值如下:
"default":自动选择,默认值。
"high-performance": 高性能模式。
"low-power": 节能模式。
premultipliedAlpha: boolean值,表明排版引擎讲假设绘制缓冲区包含预混合alpha通道,默认true。
preserveDrawingBuffer: boolean值,如果这个值为true缓冲区将不会被清除,会保存下来,直到被清除或被使用者覆盖,默认false。
stencil: boolean值,表明绘制缓冲区包含一个深度至少为8位的模版缓冲区,默认false。
?? 最新的chrome中还支持一个属性 desynchronized,它可以创建低延时渲染上下文。
实际上,除了webgl和2d上下文外,canvas还支持另外两种上下文,分别是:
webgl2 上下文,这个上下文是一个WebGL2RenderingContext渲染对象,它与webgl上下文的区别是,webgl版本基于OpenGL ES2.0,而webgl2版本基于OpenGL ES 3.0。
bitmaprenderer 上下文,它创建一个ImageBitmapRenderingContext渲染对象,可以将ImageBitmap对象的内容传入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中讨论。
关于奇舞周刊
《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。