Skip to content

57. 3D 场景如何加入音频

Published:

3D 场景很多时候是需要一些音效、背景音乐的。

那 Three.js 里如何播放音频呢?

用 Audio 相关的 api:

image.png

我们来试一下:

npx create-vite audio-api

image.png

进入项目,安装依赖:

npm install
npm install --save three
npm install --save-dev @types/three

改下 src/main.js

import './style.css';
import * as THREE from 'three';
import {
    OrbitControls
} from 'three/addons/controls/OrbitControls.js';

const scene = new THREE.Scene();

const directionLight = new THREE.DirectionalLight(0xffffff, 2);
directionLight.position.set(500, 400, 300);
scene.add(directionLight);

const ambientLight = new THREE.AmbientLight();
scene.add(ambientLight);

const width = window.innerWidth;
const height = window.innerHeight;

const helper = new THREE.AxesHelper(500);
scene.add(helper);

const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 10000);
camera.position.set(500, 600, 800);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)

function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render();

document.body.append(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

创建 Scene、Light、Camera、Renderer。

改下 style.css

body {
  margin: 0;
}

先跑下:

npm run dev

image.png

image.png

啥也没有。

我们加入音频:

这个音频下载下来:

image.png

放到 public 目录下:

image.png

然后用 AudioLoader 加载之后,用 Audio 来播放:

image.png

const listener = new THREE.AudioListener();

const audio = new THREE.Audio( listener );

const loader = new THREE.AudioLoader();
loader.load('./superman.mp3', function ( buffer ) {
  audio.setBuffer( buffer );
  audio.play();
});

这时候音乐并没有播放,devtools 打印了一条警告:

image.png

音频必须在用户交互之后才能播放。

我们这样写:

image.png

const loader = new THREE.AudioLoader();
loader.load('./superman.mp3', function ( buffer ) {
  audio.setBuffer( buffer );
});

document.body.addEventListener('click', () => {
  audio.play();
})

你点一下屏幕就好了,等音频加载完就会播放。 jaudio

audio 有很多属性方法:

image.png

document.body.addEventListener('click', () => {
  audio.setLoop(true);
  audio.setVolume(0.5);
  audio.playbackRate = 2;
  if(audio.isPlaying) {
    audio.pause();
  } else {
    audio.play();
  }
})

setLoop 设置循环播放、seetVolume 调节音量、playbackRate 调整播放速率。

isPlaying 判断播放状态,然后 pause、play 分别是暂停播放。

试下效果:

jaudio

然后我们可以用 gui 来做下可视化调节,这样可以感受下不同属性对音频的影响:

image.png

改了属性后要暂停播放才会生效:

image.png

const gui = new GUI();
const obj = {
    volume: 1,
    loop: true,
    playbackRate: 1,
    offset: 0,
    detune: 0,
    play() {
      audio.play();
    },
    pause() {
      audio.pause();
    }
}
gui.add(obj, 'volume', 0, 1).onChange(value => {
  audio.setVolume(value);
});
gui.add(obj, 'playbackRate', [0.5, 1, 2]).onChange(value => {
  audio.playbackRate = value;
  audio.pause();
  audio.play();
});
gui.add(obj, 'loop').onChange(value => {
  audio.setLoop(value);
  audio.pause();
  audio.play();
});
gui.add(obj, 'offset', 0, 150).onChange(value => {
  audio.offset = value;
  audio.pause();
  audio.play();
});
gui.add(obj, 'detune', 0, 1000).onChange(value => {
  audio.detune = value;
  audio.pause();
  audio.play();
});
gui.add(obj, 'play');
gui.add(obj, 'pause');

试下效果:

比如调整 offset:

2025-04-08 11.56.02.gif

jaudio

再调解下播放速率 playbackRate:

2025-04-08 11.58.36.gif

jaudio

调节下音高:

2025-04-08 12.01.46.gif

jaudio

案例代码上传了小册仓库

总结

这节我们学了 Three.js 如何播放音频。

主要是通过 AudioLoader 加载音频,之后用 Audio 来播放,通过 setBuffer 设置音频数据。

通过 volume、playbackRate、offset、detune 等来调节音频效果。

后面需要用到音频的地方,都可以通过 Audio 来实现。

评论