如何在没有闪烁的情况下调整画布大小?

时间:2013-07-22 02:39:43

标签: canvas three.js webgl

当调整窗口大小或框架具有白色边框时,许多Three.js样本会闪烁。例如:http://threejs.org/examples/webgl_animation_skinning.html

另一方面,WebGL Aquarium不会闪烁。这是怎么做到的?

3 个答案:

答案 0 :(得分:1)

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>

或小提琴http://jsfiddle.net/greggman/pfWS3/

答案 1 :(得分:1)

调整窗口大小后,您需要立即调用渲染。

更好的是你可以拥有requestAnimationFrame并调整大小,然后在一个函数调用中渲染。它将确保回流和渲染在一次回流中直接发生,而不是分开导致闪烁。

答案 2 :(得分:1)

function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.render(scene, camera);
    }