2024-09-16|閱讀時間 ‧ 約 20 分鐘

使用howler.js 在vue頁面播放音效

howler.js是一個強大的 JavaScript 音效庫,可以方便地在網頁上播放音效。

在 Vue.js 中使用 Howler.js 可以輕鬆地管理和播放音效。

  • npm安裝
npm install howler
  • 如果使用Typescript,由於Howler.js 沒有提供內置的 TypeScript 類型定義檔案,所以需要手動為 Howler 添加類型定義。
  1. 在項目根目錄下創建一個 types 文件夾(如果還沒有)。
  2. types 文件夾中創建一個 howler.d.ts 文件。
  3. howler.d.ts 文件中添加以下內容:
declare module 'howler' {
export class Howl {
constructor(options: HowlOptions);
play(sprite?: string | number): number;
pause(id?: number): void;
stop(id?: number): void;
mute(muted?: boolean, id?: number): void;
volume(volume?: number, id?: number): number;
fade(from: number, to: number, duration: number, id?: number): void;
rate(rate?: number, id?: number): number;
seek(seek?: number, id?: number): number;
loop(loop?: boolean, id?: number): boolean;
playing(id?: number): boolean;
duration(id?: number): number;
state(): string;
load(): void;
unload(): void;
on(event: string, handler: (id?: number) => void): void;
off(event: string, handler?: (id?: number) => void): void;
once(event: string, handler: (id?: number) => void): void;
}

export interface HowlOptions {
src: string | string[];
volume?: number;
html5?: boolean;
loop?: boolean;
preload?: boolean;
autoplay?: boolean;
mute?: boolean;
rate?: number;
pool?: number;
format?: string | string[];
xhrWithCredentials?: boolean;
onload?: () => void;
onloaderror?: (id: number, error: any) => void;
onplay?: (id: number) => void;
onend?: (id: number) => void;
onpause?: (id: number) => void;
onstop?: (id: number) => void;
onmute?: (id: number) => void;
onvolume?: (id: number) => void;
onrate?: (id: number) => void;
onseek?: (id: number) => void;
onfade?: (id: number) => void;
onunlock?: (id: number) => void;
}
}
  • 快速使用範例
<script setup lang="ts">
//引入 Howler.js
import { Howl } from 'howler';
//創建 Howl 實例:(此範例是將sample.mp3 放置於public/audio)
const sound = new Howl({ src: ['audio/sample.mp3'] });
//播放音效
const playSound = () => {
sound.play();
}
</script>
  • 基本使用範例
<template>
<div>
<button @click="playSound">播放音效</button>
<button @click="pauseSound">暫停音效</button>
<button @click="stopSound">停止音效</button>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Howl } from 'howler';

// 創建一個 ref 來保存 Howl 實例
const sound = ref<Howl | null>(null);

// 播放音效的方法
const playSound = () => {
if (!sound.value) {
sound.value = new Howl({
src: ['path/audio/sample.mp3']
});
}
sound.value.play();
};

// 暫停音效的方法
const pauseSound = () => {
if (sound.value) {
sound.value.pause();
}
};

// 停止音效的方法
const stopSound = () => {
if (sound.value) {
sound.value.stop();
}
};
</script>


  • 設置音量
const sound = new Howl({
src: ['/audio/sample.mp3'],
volume: 0.5 // 設置音量為 50%
});
  • 全局設置音量(需要引入Howler)
import { Howler } from 'howler';

// 設置全局音量為 50%
Howler.volume(0.5);

引入Howler,之前所提到的howler.d.ts 需要補以下內容

// 新增 Howler 全局對象的聲明
export const Howler: {
volume(volume?: number): number; // 控制全局音量
mute(muted: boolean): void; // 控制全局靜音
codecs(ext: string): boolean; // 檢查瀏覽器支持的音頻格式
stop(): void; // 停止所有音效
unload(): void; // 卸載所有音效
};
  • 控制全局音量範例
<template>
<div>
<button @click="playSound">播放音效</button>
<input type="range" min="0" max="1" step="0.1" v-model="volume"
@input="setGlobalVolume(volume)">
<label>全局音量: {{ volume }}</label>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Howl, Howler } from 'howler';

// 音量狀態,初始值為 0.5
const volume = ref(0.5);

// 用來儲存 Howl 實例的變數
const sound = ref<Howl | null>(null);

// 播放音效的函數
const playSound = () => {
if (!sound.value) {
sound.value = new Howl({
src: ['audio/sample.mp3']
});
}
sound.value.play();
};

// 設置全局音量的函數
const setGlobalVolume = (newVolume: number) => {
Howler.volume(newVolume);
};
</script>
  • 循環播放(加上loop: true ​)
// 播放循環音效的函數
const playLoopingSound = () => {
if (!sound.value) {
sound.value = new Howl({
src: ['path/to/your/audio/file.mp3'],
loop: true,
});
}
sound.value.play();
};
  • 監聽音效事件(onend, onplay, onpause, onstop, onloaderror)
<template>
<div>
<button @click="playSoundWithEvents">播放音效並監聽事件</button>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Howl } from 'howler';

// 儲存 Howl 實例的變數
const sound = ref<Howl | null>(null);

// 播放音效並監聽事件
const playSoundWithEvents = () => {
if (!sound.value) {
sound.value = new Howl({
src: ['audio/sample.mp3'],
onend: () => {
console.log('音效播放完畢');
},
onplay: () => {
console.log('音效開始播放');
},
onpause: () => {
console.log('音效暫停');
},
onstop: () => {
console.log('音效停止');
},
onloaderror: (id, error) => {
console.error('音效加載失敗', error);
}
});
}
sound.value.play();
};
</script>


  • 預加載音效

在 Howler.js 中,音效預加載是默認行為,當創建一個 Howl 實例時,音效文件就會開始加載。

可以通過 autoplay: false(默認)和 preload: true(默認)來控制的。

當 preload 設置為 true 時,音效會在創建 Howl 實例後自動預加載。

可以透過監聽 onload 事件來確定音效是否已經加載完畢。

<template>
<div>
<button @click="playSound" :disabled="!isLoaded">播放音效</button>
<p v-if="!isLoaded">音效加載中...</p>
<p v-if="isLoaded">音效已加載,點擊按鈕播放</p>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Howl } from 'howler';

// 音效加載狀態
const isLoaded = ref(false);

// 用來儲存 Howl 實例的變數
const sound = ref<Howl | null>(null);

// 創建 Howl 實例並預加載音效
sound.value = new Howl({
src: ['audio/sample.mp3'],
preload: true, // 預加載音效(默認是 true)
onload: () => {
isLoaded.value = true; // 當音效加載完畢時設置為 true
console.log('音效已加載');
},
onloaderror: (id, error) => {
console.error('音效加載失敗', error);
}
});

// 播放音效
const playSound = () => {
if (sound.value && isLoaded.value) {
sound.value.play();
}
};
</script>
  • 多個音效預加載
<script setup lang="ts">
import { onMounted } from 'vue';
import { Howl } from 'howler';

// 音效加載狀態
const allLoaded = ref(false);
const sounds: Howl[] = [];

// 在組件加載時預加載所有音效
onMounted(() => {
const soundFiles = [
'audio/1.mp3',
'audio/2.mp3',
'audio/3.mp3'
];

let loadedCount = 0;

soundFiles.forEach((src) => {
const sound = new Howl({
src: [src],
preload: true,
onload: () => {
loadedCount++;
if (loadedCount === soundFiles.length) {
allLoaded.value = true;
console.log('所有音效已加載');
}
},
onloaderror: (id, error) => {
console.error('音效加載失敗', error);
}
});
sounds.push(sound);
});
});
</script>

當所有音效文件都加載完畢時,更新 allLoaded 變數,表示所有音效已經準備好播放。

  • 懶加載
<template>
<div>
<button @click="playSound('audio1')">播放音效 1</button>
<button @click="playSound('audio2')">播放音效 2</button>
<button @click="playSound('audio3')">播放音效 3</button>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Howl } from 'howler';

// 儲存 Howl 實例的對象,按需創建和載入音效
const sounds: { [key: string]: Howl | null } = {
audio1: null,
audio2: null,
audio3: null,
};

// 音效的文件路徑
const soundFiles = {
audio1: 'audio/1.mp3',
audio2: 'audio/2.mp3',
audio3: 'audio/3.mp3',
};

// 播放音效的函數,按需加載音效
const playSound = (name: string) => {
if (!sounds[name]) {
// 懶加載音效:當音效第一次播放時才創建對應的 Howl 實例
sounds[name] = new Howl({
src: [soundFiles[name]],
preload: false, // 延遲加載音效,直到需要播放
onload: () => {
console.log(`${name} 已加載`);
},
onloaderror: (id, error) => {
console.error(`${name} 加載失敗`, error);
}
});
}
// 確保音效已經存在並開始播放
sounds[name]?.play();
};
</script>


  • 使用音效物件方式播放音效
import { Howl } from 'howler';

interface AudioManager {
sounds: { [key: string]: Howl };
preloadAll: () => void;
play: (name: string) => void;
playingBlockInstances: number;
maxBlockInstances: number;
}
const soundMuted = ref(false);
const isStop = ref(false);
const audioManager: AudioManager = {
// 宣告音效物件
sounds: {
error: new Howl({ src: ['/audio/error.mp3'] }),
win: new Howl({ src: ['/audio/win.mp3'] }),
click: new Howl({ src: ['/audio/click.mp3'] })
},
// 預加載
preloadAll() {
Object.values(this.sounds).forEach((sound) => {
sound.load();
});
},

// 播放音效函式
play(name: string) {
if (soundMuted) return;
const sound = this.sounds[name];
if (sound) {
const id = sound.play();
if(isStop.value) {
sound.stop(id);
}
} else {
console.error(`Sound ${name} not found!`);
}
},
};

// 播放音效的物件方法
const playSnd = {
win: () => audioManager.play('win'),
click () => audioManager.play('bet'),
err: () => audioManager.play('error')
};

playSnd.click(); //播放按鈕音效


  • 其他補充

sound.once 註冊一次性事件監聽器,只會觸發一次


分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.