Three.js предоставляет удобные инструменты для работы с аудио на основе Web Audio API. Звук может быть:
- статическим (Audio) – просто воспроизводится в сцене;
- позиционным (PositionalAudio) – его громкость и панорама зависят от положения источника относительно камеры.
Для работы со звуком необходимо:
- Добавить в сцену AudioListener и привязать его к камере.
- Загрузить звуковой файл с помощью AudioLoader.
- Создать объект звука (Audio или PositionalAudio) и связать с ним загруженный буфер.
- Добавить звук в сцену и управлять воспроизведением.
Пример позиционного звука, который движется вместе с объектом:
import * as THREE from 'three';
import { OrbitControls } from 'https://unpkg.com/three@0.128.0/examples/jsm/controls/OrbitControls.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(2, 2, 5);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 1. Создаём слушатель и прикрепляем к камере
const listener = new THREE.AudioListener();
camera.add(listener);
// 2. Загружаем звук
const audioLoader = new THREE.AudioLoader();
const sound = new THREE.PositionalAudio(listener); // позиционный звук
audioLoader.load('sound.mp3', (buffer) => {
sound.setBuffer(buffer);
sound.setRefDistance(2); // расстояние, на котором громкость нормальная
sound.setVolume(0.8);
sound.setLoop(true); // зацикливание
// sound.play(); // воспроизведение – обычно по взаимодействию
});
// 3. Создаём объект, к которому привяжем звук
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x44aa88 });
const cube = new THREE.Mesh(geometry, material);
cube.add(sound); // звук будет следовать за кубом
scene.add(cube);
// Свет и управление
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 2, 1);
scene.add(light);
const controls = new OrbitControls(camera, renderer.domElement);
// Анимация
function animate() {
requestAnimationFrame(animate);
cube.rotation.y += 0.01;
controls.update();
renderer.render(scene, camera);
}
animate();
// Включаем звук только после взаимодействия пользователя (политика браузера)
window.addEventListener('click', () => {
if (!sound.isPlaying) sound.play();
});Ключевые моменты:
- AudioListener должен быть прикреплён к камере – это «уши» слушателя.
- Для позиционного звука важен параметр setRefDistance – чем он меньше, тем быстрее затухает звук с расстоянием.
- Современные браузеры запрещают автоматическое воспроизведение звука без жеста пользователя. Поэтому play() обычно вызывается по клику или нажатию клавиши.
- Можно использовать Audio вместо PositionalAudio, если источник не должен зависеть от положения.