В Three.js сцена создаётся с использованием объекта
THREE.WebGLRenderer, который отрисовывает графику на
элементе <canvas>. Размер этого канваса напрямую
влияет на качество изображения и соотношение сторон сцены. Для
корректного отображения необходимо синхронизировать размеры рендерера с
размерами окна браузера и обновлять камеру при изменении этих
размеров.
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
Ключевой момент: renderer.setSize(width, height) задаёт
внутренние размеры канваса, что напрямую влияет на разрешение и качество
отрисовки.
Наиболее часто используется перспективная камера
THREE.PerspectiveCamera. Она требует указания угла
обзора (fov), соотношения сторон (aspect), а
также ближней и дальней плоскостей обрезки (near, far).
Соотношение сторон камеры должно соответствовать соотношению сторон
рендерера:
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
При изменении размеров окна необходимо обновлять
aspect камеры и вызывать
camera.updateProjectionMatrix(), чтобы предотвратить
искажения изображения.
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
window.devicePixelRatioДля поддержки дисплеев с высокой плотностью пикселей
(Retina и аналогичных) важно учитывать
window.devicePixelRatio. Это позволяет избежать размытия и
повышает качество рендеринга.
renderer.setPixelRatio(window.devicePixelRatio);
Следует применять это в комбинации с setSize, чтобы
канвас правильно масштабировался:
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
Для приложений с динамическим переходом в полноэкранный режим
рекомендуется использовать событие fullscreenchange:
document.addEventListener('fullscreenchange', () => {
const width = window.innerWidth;
const height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
Это гарантирует корректное масштабирование сцены при любом размере экрана, включая мобильные устройства.
Изменение размеров окна браузера может происходить часто, что потенциально создаёт нагрузку на рендерер. Для снижения количества операций используют дебаунсинг:
let resizeTimeout;
window.addEventListener('resize', () => {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, 100);
});
Это позволяет обновлять рендерер не при каждом пикселе изменения, а с разумной задержкой, повышая общую производительность.
Некоторые объекты сцены и элементы интерфейса (например, 2D-спрайты или текстовые метки) требуют динамического пересчёта своих размеров и позиций в зависимости от размеров окна. Для этого можно использовать относительные единицы:
sprite.scale.set(window.innerWidth * 0.1, window.innerHeight * 0.1, 1);
sprite.position.set(window.innerWidth * 0.5, window.innerHeight * 0.5, 0);
При изменении окна необходимо обновлять такие параметры в обработчике
resize, чтобы элементы оставались пропорциональными.
Если используется THREE.OrbitControls или аналогичные
средства управления камерой, важно вызывать
controls.update() после изменения размеров камеры, чтобы
интерфейс корректно реагировал на новые параметры сцены:
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.update();
});
renderer.setPixelRatio(window.devicePixelRatio) для высокой
четкости.camera.aspect и вызывать
camera.updateProjectionMatrix() при каждом изменении
размеров окна.Адаптация к размеру окна — ключевой аспект при создании интерактивных 3D-приложений, обеспечивающий правильное отображение, высокое качество и отзывчивость интерфейса.