Estoy creando una escena básica en threejs y haciendo que el lienzo responda para crear una experiencia de pantalla completa. La malla que está dentro de la escena no cambia de tamaño correctamente. Se supone que es un cubo, pero se convierte en un rectángulo si se cambia de tamaño.
const scene = new THREE.Scene(); const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); const sizes = { width: window.innerWidth, height: window.innerHeight } //responsive canvas const canvas = document.querySelector('.webgl'); window.addEventListener('resize', () => { sizes.width = window.innerWidth; sizes.height = window.innerHeight; camera.aspect = sizes.width / sizes.height; camera.updateProjectionMatrix(); renderer.setSize(sizes.width, sizes.height); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) }); const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height); camera.position.z = 3 scene.add(camera) const renderer = new THREE.WebGLRenderer({ canvas: canvas }); renderer.setSize(sizes.width, sizes.height); renderer.render(scene, camera); <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <canvas class="webgl"></canvas>Este es el resultado esperado:
pero al cambiar el tamaño de la ventana, el cubo adquiere una escala extraña:
Dado que no hay un ciclo de animación en su escena, debe llamar a renderer.render para cambiar el resize manualmente:
const scene = new THREE.Scene(); const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); const sizes = { width: window.innerWidth, height: window.innerHeight } //responsive canvas const canvas = document.querySelector('.webgl'); window.addEventListener('resize', () => { sizes.width = window.innerWidth; sizes.height = window.innerHeight; camera.aspect = sizes.width / sizes.height; camera.updateProjectionMatrix(); renderer.setSize(sizes.width, sizes.height); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) renderer.render(scene, camera); // -> Also needed }); const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height); camera.position.z = 3 scene.add(camera) const renderer = new THREE.WebGLRenderer({ canvas: canvas }); renderer.setSize(sizes.width, sizes.height); renderer.render(scene, camera); <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <canvas class="webgl"></canvas>Un ejemplo con un bucle de animación:
const scene = new THREE.Scene(); const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); const sizes = { width: window.innerWidth, height: window.innerHeight } //responsive canvas const canvas = document.querySelector('.webgl'); window.addEventListener('resize', () => { sizes.width = window.innerWidth; sizes.height = window.innerHeight; camera.aspect = sizes.width / sizes.height; camera.updateProjectionMatrix(); renderer.setSize(sizes.width, sizes.height); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) // renderer.render(scene, camera); // -> Not needed since it is called in animate() }); const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height); camera.position.z = 3 scene.add(camera) const renderer = new THREE.WebGLRenderer({ canvas: canvas }); renderer.setSize(sizes.width, sizes.height); function animate(time) { time *= 0.001; // seconds mesh.rotation.x = time * 0.5; mesh.rotation.y = time * 1; renderer.render(scene, camera); // Is called continuously here requestAnimationFrame(animate); } requestAnimationFrame(animate); <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <canvas class="webgl"></canvas>