【发布时间】:2013-07-20 16:33:11
【问题描述】:
许多 Three.js 示例在调整窗口大小或框架具有白色边框时会闪烁。例如:http://threejs.org/examples/webgl_animation_skinning.html
另一方面,WebGL Aquarium 不闪烁。这是怎么做到的?
【问题讨论】:
许多 Three.js 示例在调整窗口大小或框架具有白色边框时会闪烁。例如:http://threejs.org/examples/webgl_animation_skinning.html
另一方面,WebGL Aquarium 不闪烁。这是怎么做到的?
【问题讨论】:
AFAICT 大多数 Three.JS 示例通过查看窗口大小或容器大小,然后设置 canvas.width、canvas.height 来手动设置画布的大小。
另一方面,包括 WebGL Aquarium 在内的 TDL 示例使用 CSS 让浏览器缩放画布,然后在 requestAnimationFrame 回调中更新画布后备存储的大小。
这是一个例子
const gl = document.querySelector("#c").getContext("webgl");
function render() {
resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// Draw a 2 pixel border around the edge using
// the scissor test since it's easier than setting up
// a lot of stuff
gl.clearColor(1, 0, 0, 1); // red
gl.disable(gl.SCISSOR_TEST);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.enable(gl.SCISSOR_TEST);
gl.scissor(2, 2, gl.canvas.width - 4, gl.canvas.height - 4);
gl.clearColor(0, 0, 1, 1); // blue
gl.clear(gl.COLOR_BUFFER_BIT);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
}
}
body {
margin: 0;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
<canvas id="c"></canvas>
【讨论】:
调整窗口大小后需要立即调用渲染。
更好的是,您可以拥有requestAnimationFrame 并在一个函数调用中调整大小然后渲染。它将确保回流和渲染在一次回流中立即发生,而不是分开导致闪烁。
【讨论】:
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
【讨论】: