这是重置画布尺寸时应该知道的知识。
每个画布都有两个尺寸,一个是 drawingbuffer 的尺寸, 这个表示画布中有多少个像素。另一是画布显示的尺寸, CSS决定画布显示的尺寸。
你可以通过两种方式设置画布的 drawingbuffer尺寸。一种是使用HTML
<canvas id="c" width="400" height="300"></canvas>
另一种是使用JavaScript
<canvas id="c" ></canvas>
JavaScript
var canvas = document.querySelector("#c");
canvas.width = 400;
canvas.height = 300;
如果你没有使用CSS影响到画布的显示尺寸,画布的显示尺寸则和 drawingbuffer 尺寸相同。 所以在上述两个例子中画布的 drawingbuffer 尺寸和显示尺寸都是 400x300。
在下方的例子中画布的显示尺寸是 400x300,drawingbuffer 是 10x15
<canvas id="c" width="10" height="15" style="width: 400px; height: 300px;"></canvas>
或者像这样
<style>
#c {
width: 400px;
height: 300px;
}
</style>
<canvas id="c" width="10" height="15"></canvas>
如果我们在画布上绘制以一个单像素宽度的线,就会得到这样的结果
为什么它被模糊了?因为浏览器得到 10x15 像素的画布,将它拉伸到 400x300 像素, 然后在拉伸的过程中进行了插值。
假设我们想让画布填充满窗口该怎么做?首先使用CSS让浏览器将画布铺满窗口,例如
<html>
<head>
<style>
/* 移除边界 */
body {
border: 0;
background-color: white;
}
/* 设置欢度大小为视域大小 */
canvas {
width: 100vw;
height: 100vh;
display: block;
}
<style>
</head>
<body>
<canvas id="c"></canvas>
</body>
</html>
现在只需要将 drawingbuffer 的尺寸设置为为浏览器拉伸后的画布尺寸。
我们可以使用 clientWidth
和 clientHeight
属性,这个属性是所有HTML元素都有的属性,
可以让JavaScript获取元素显示的尺寸。
function resize(canvas) {
// 获取浏览器中画布的显示尺寸
var displayWidth = canvas.clientWidth;
var displayHeight = canvas.clientHeight;
// 检尺寸是否相同
if (canvas.width != displayWidth ||
canvas.height != displayHeight) {
// 设置为相同的尺寸
canvas.width = displayWidth;
canvas.height = displayHeight;
}
}
大多数WebGL应用是变化的,所以我们需要在绘制之前调用这个方法调画布为期望的大小。
function drawScene() {
resize(gl.canvas);
...
这是结果
哪里出问题了?为什么这个线没有覆盖整个区域?
原因是当我们重置画布尺寸的时候还需要调用gl.viewport
设置视域,
gl.viewport
告诉WebGL如何将裁剪空间(-1 到 +1)中的点转换到像素空间,
也就是画布内。当你第一次创建WebGL上下文的时候WebGL会设置视域大小和画布大小匹配,
但是在那之后就需要你自己设置。当你改变画布大小就需要告诉WebGL新的视域设置。
让我们来修改代码处理这个问题。由于WebGL上下文引用了画布,所以直接传递它的尺寸。
function drawScene() {
resize(gl.canvas);
+ gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
...
现在没问题了。
在新窗口中打开,改变窗口大小,发现它总是填满窗口。
我知道你会问,为什么WebGL不在画布尺寸改变的时候自动帮我们修改视域? 原因是它不知道你如何以及为什么使用视域, 你可以渲染到一个帧缓冲或者做其他的事情需要不同的视域尺寸。 WebGL没办法知道你的意图所以就不能自动帮你设置视域。
如果你看了很多WebGL应用他们处理或者设置画布尺寸有很多不同的方式, 如果你好奇的话这里有一些我认为比较合适的方式。