You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ThreeJS问题咨询:renderer.setSize执行顺序异常与Canvas动态适配需求

Why does renderer.setSize() run before earlier code in Three.js? And how to fit Canvas to Plane dimensions dynamically?

Hey there! Let's tackle your questions one by one—this is a super common gotcha with asynchronous code in JavaScript, so you're not alone here.

1. Why does renderer.setSize() execute before your model loading logic?

The core issue here is asynchronous operations. When you use a loader (like GLTFLoader or OBJLoader) to fetch a model from local storage (or any external source), the load() method doesn't block the rest of your code from running. Instead:

  • Your initial renderer.setSize(800, 600) runs immediately because it's synchronous code.
  • The loader sends a request to fetch the model, but while it waits for that request to complete, JavaScript moves on to execute the next lines of code (which might include another unintended renderer.setSize() call).
  • Only once the model finishes loading does the loader's onLoad callback fire—by then, your earlier setSize has already run.

It's not that setSize is "out of order"—it's just that asynchronous tasks don't follow the linear top-to-bottom flow you might expect for synchronous code.

2. How to dynamically resize Canvas to match loaded Plane dimensions

To fix this, you need to move your renderer.setSize() logic inside the model's load completion callback. That way, you only adjust the Canvas size after you have the Plane's actual dimensions. Here's a concrete example:

Before (the problematic order):

// Initial Canvas setup (runs first)
const renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 600);
document.body.appendChild(renderer.domElement);

// Model loading (asynchronous, runs in background)
const loader = new THREE.GLTFLoader();
loader.load('path/to/your-plane.gltf', function(gltf) {
  const plane = gltf.scene.children.find(child => child instanceof THREE.Mesh);
  // This code runs LATER, after setSize already executed
});

// Accidental extra setSize that runs before model loads
renderer.setSize(800, 600); // Oops, this runs immediately too!

After (fixed, size adjusts after model loads):

// Initial Canvas setup (temporary size)
const renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 600); // Temporary initial size
document.body.appendChild(renderer.domElement);

const camera = new THREE.PerspectiveCamera(75, 800/600, 0.1, 1000);
camera.position.z = 5;

const scene = new THREE.Scene();

// Model loading (wait for this to finish before resizing)
const loader = new THREE.GLTFLoader();
loader.load('path/to/your-plane.gltf', function(gltf) {
  const plane = gltf.scene.children.find(child => child instanceof THREE.Mesh);
  scene.add(plane);

  // Now we have the Plane's actual dimensions!
  const planeWidth = plane.scale.x * plane.geometry.parameters.width;
  const planeHeight = plane.scale.y * plane.geometry.parameters.height;

  // Resize renderer to match Plane dimensions
  renderer.setSize(planeWidth, planeHeight);

  // Update camera aspect ratio to match new Canvas size
  camera.aspect = planeWidth / planeHeight;
  camera.updateProjectionMatrix();

  // Render the scene with the new size
  renderer.render(scene, camera);
}, undefined, function(error) {
  console.error('Error loading model:', error);
});

// Your animation loop (if you have one)
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

Key points here:

  • We only call renderer.setSize() after we've accessed the loaded Plane's dimensions.
  • Don't forget to update the camera's aspect ratio and call camera.updateProjectionMatrix()—otherwise, your scene will look stretched.
  • If you're using a different loader (like creating PlaneBufferGeometry directly instead of loading a model), the same logic applies: wait until the geometry is ready before adjusting the Canvas size.

内容的提问来源于stack exchange,提问作者Yone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:28:27