threejs 响应式 canvas 无法正确调整网格大小
threejs responsive canvas doesn't resize mesh correctly
我正在 threejs 上创建一个基本场景并使 canvas 响应以创建全屏体验。场景内的网格未正确调整大小。它应该是一个立方体,但如果调整大小就会变成一个矩形。
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>
这是预期的结果:
但是在 window 调整大小时,立方体得到了一个奇怪的比例:
由于您的场景中没有动画循环,您需要在 resize
上手动调用 renderer.render
:
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>
动画循环示例:
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>
我正在 threejs 上创建一个基本场景并使 canvas 响应以创建全屏体验。场景内的网格未正确调整大小。它应该是一个立方体,但如果调整大小就会变成一个矩形。
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>
这是预期的结果:
但是在 window 调整大小时,立方体得到了一个奇怪的比例:
由于您的场景中没有动画循环,您需要在 resize
上手动调用 renderer.render
:
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>
动画循环示例:
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>