返回

Three.js 响应式:打造无缝适配的 3D 体验

前端

Three.js 响应式场景设计

Three.js 是一个功能强大的 JavaScript 库,用于创建和渲染交互式 3D 图形。为了提供无缝的用户体验,响应式设计至关重要,它允许 3D 场景适应不同设备和窗口大小的变化。

克服渲染模糊问题

Three.js 场景中的对象边缘模糊通常是由抗锯齿不足引起的。抗锯齿是一种技术,它通过混合相邻像素的颜色来平滑锯齿状边缘。我们可以通过启用场景中的抗锯齿来解决这个问题。

renderer.setClearColor(0x000000, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);

保持场景比例

当容器大小改变时,场景中的图像可能会被压缩或拉伸。为了保持场景的正确纵横比,我们需要调整相机的纵横比以匹配容器的宽高比。

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

调整视口尺寸

Three.js 场景渲染到一个 canvas 元素中。为了使场景填满整个容器,我们需要调整视口的尺寸以匹配容器的尺寸。

renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);

事件监听

为了响应窗口大小的变化,我们需要监听 resize 事件。当检测到窗口大小变化时,我们可以执行上述步骤来更新场景。

window.addEventListener('resize', function() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
});

代码示例

下面是一个完整的代码示例,展示了如何实现一个响应式的 Three.js 场景:

import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

const animate = function () {
  requestAnimationFrame(animate);

  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
};

animate();

window.addEventListener('resize', function() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
});