ThreeJs学习笔记【day4】响应式场景

190 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情 >>

前言

这篇文章尝试去说明如何让ThreeJs创建的场景适应各种变化,为了方便写代码,本文里对于扩展对象的引用将会采用module的方式直接引入,不再演示如何进行去模块化改造。

前期准备

利用之前的学习笔记,快速构建一个场景,在场景中放置立方体,添加光源,代码较多,所以用代码片段的方式进行引入

下面将利用当前构造立方体的代码,进行响应式场景改造 首先我们通过设置css的方式,让canvas元素充满屏幕,canvas默认是行内块,行内块在结尾有空格,所以需要设置为块元素

#c {
    width: 100%;
    height: 100%;
    display: block;
}

image.png

这个时候立方体他,不清晰了,而且拉伸了

解决立方体被拉伸

立方体被拉伸是因为相机宽高比和渲染立方体的canvas宽高比不一致导致的,这里需要设置一下

const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 75;
const aspect = window.innerWidth/ window.innerHeight;  // 相机默认值
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
+ camera.aspect = canvas.clientWidth / canvas.clientHeight;
+ camera.updateProjectionMatrix();

image.png 这样拉伸变形就处理好了,看起来像一个正方形了

解决锯齿

canvs是有两个宽高的,一个就是css设置的宽高,也叫画布宽高,还有一个,是canvas内像素的数量,就好像img标签的宽高属性一样,img同样也有两个宽高。

一个canvas的内部尺寸,它的分辨率,学名被叫做绘图缓冲区(drawingbuffer)尺寸。这里显然是因为canvas分辨率和他的宽高不一致导致的,这里就需要把他们处理成一致的。

function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}
function render(time) {
  time *= 0.001;  // 将时间单位变为秒
 
  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  .........

image.png

高分屏处理

  1. 不做任何处理,因为threejs会自动帮我们做这样的工作。
  2. renderer.setPixelRatio(window.devicePixelRatio); 让渲染器适配高分屏物理分辨率,这样做会导致你每次调用rerender.setSize的时候,都会自动乘以像素比
  3. 在检测canvas宽高的时候处理
function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement
  const pixelRatio = window.devicePixelRatio
  const width = canvas.clientWidth * (pixelRatio | 1)
  const height = canvas.clientHeight * (pixelRatio | 1)
  const needResize = canvas.width !== width || canvas.height !== height
  if (needResize) {
    renderer.setSize(width, height, false)
  }
  return needResize
}

完整代码以代码片段的方式引入