Threejs的场景有时候需要引入声音,比如下雨声音,撞击声音等,这需要用到Threejs的两个类Audio和PositionalAudio,第一个Audio是普通的声音,比如下雨,在整个场景中听到的都是下雨的声音,而且每个位置的声音都一样大小,那么就需要用Audio,也可以作为3D场景的背景音乐来用,但是如果是某个位置发生了撞击,那么应该是距离越远,听到撞击的声音越小,也就是要把声源的位置固定,把耳朵绑定到相机上,相机距离声源越远听到的声音越小,相机距离声源越近听到的声音越大,此外,如果撞击声音在左侧,那么应该左侧耳机声音更大,如果撞击发生在右侧,正好想反,下面看下整个过程:
首先创建场景:
initScene(){
scene = new THREE.Scene();
},
initCamera(){
this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
this.camera.position.set(10,10,10);
this.camera.lookAt(0,0,0)
},
initLight(){
//添加两个平行光
const directionalLight1 = new THREE.DirectionalLight(0xffffff, 1.5);
directionalLight1.position.set(300,300,600)
scene.add(directionalLight1);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 1.5);
directionalLight2.position.set(600,200,600)
scene.add(directionalLight2);
},
initRenderer(){
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.container = document.getElementById("container")
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
this.renderer.setClearColor('#AAAAAA', 1.0);
this.container.appendChild(this.renderer.domElement);
},
initControl(){
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.enableDamping = true;
this.controls.maxPolarAngle = Math.PI / 2.2; // // 最大角度
},
initAnimate() {
requestAnimationFrame(this.initAnimate);
this.renderer.render(scene, this.camera);
},
然后创建监听和声音,先创建一个监听:AudioListener,再创建一个Audio加载器用来加载声音,
AudioLoader,然后播放声音就可以了,
initAudio(){
// 创建一个监听者
let listener = new THREE.AudioListener();
// 创建一个非位置音频对象 用来控制播放
let audio = new THREE.Audio(listener);
// 创建一个音频加载器对象
let audioLoader = new THREE.AudioLoader();
// 加载音频文件,返回一个音频缓冲区对象作为回调函数参数
audioLoader.load('/static/video/music.mp3', function(AudioBuffer) {
// 音频缓冲区对象关联到音频对象audio
audio.setBuffer(AudioBuffer);
audio.setLoop(true); //是否循环
audio.setVolume(0.5); //音量
// 播放缓冲区中的音频数据
audio.play();
});
},
这里也可以用一个简单的用html隐藏一个audio标签实现,并用js控制,因为这里不会对音乐做特殊的处理,这里就不演示效果了。
再来试下位置音频,同样是加载一个监听和一个声音,但是这里为了了解音频的位置,所以先创建一个模型,将音频绑定到模型上,后面就可以通过改变相机的位置,体验下不同距离和位置对听到的声音的影响。
initAudio(){
let geometry = new THREE.BoxGeometry(2,2,2);
let material = new THREE.MeshPhysicalMaterial({color:'#1c32b5'});
let audioMesh = new THREE.Mesh(geometry, material);
// 设置网格模型的位置,相当于设置音源的位置
audioMesh.position.set(0, 0, 0);
scene.add(audioMesh);
// 创建一个虚拟的监听者
let listener = new THREE.AudioListener();
// 监听者绑定到相机对象
this.camera.add(listener);
// 创建一个位置音频对象,监听者作为参数,音频和监听者关联。
let PosAudio = new THREE.PositionalAudio(listener);
//音源绑定到一个网格模型上
audioMesh.add(PosAudio);
// 创建一个音频加载器
let audioLoader = new THREE.AudioLoader();
// 加载音频文件,返回一个音频缓冲区对象作为回调函数参数
audioLoader.load('/static/video/music.mp3', function(AudioBuffer) {
// console.log(buffer);
// 音频缓冲区对象关联到音频对象audio
PosAudio.setBuffer(AudioBuffer);
PosAudio.setVolume(0.9); //音量
PosAudio.setRefDistance(200); //参数值越大,声音越大
PosAudio.play(); //播放
});
},
效果如下:
threejs场景下的音频和位置音频