基于Vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音播放功能的示例代碼
我將為您創(chuàng)建一個(gè)完整的Vue文字轉(zhuǎn)語(yǔ)音播放應(yīng)用,具有美觀的界面和完整的交互功能。
設(shè)計(jì)思路
- 使用Web Speech API的SpeechSynthesis功能
- 創(chuàng)建直觀的控制界面,包含播放/暫停、停止、語(yǔ)速和音調(diào)調(diào)節(jié)
- 添加語(yǔ)音選擇功能
- 設(shè)計(jì)響應(yīng)式布局,適配不同設(shè)備
實(shí)現(xiàn)代碼
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue文字轉(zhuǎn)語(yǔ)音播放器</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<link rel="stylesheet" rel="external nofollow" >
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
width: 100%;
max-width: 800px;
background-color: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
overflow: hidden;
}
.header {
background: linear-gradient(to right, #4a00e0, #8e2de2);
color: white;
padding: 25px;
text-align: center;
}
.header h1 {
font-size: 2.2rem;
margin-bottom: 10px;
}
.header p {
opacity: 0.9;
font-size: 1.1rem;
}
.content {
padding: 30px;
}
.text-input {
margin-bottom: 25px;
}
.text-input label {
display: block;
margin-bottom: 10px;
font-weight: 600;
color: #333;
font-size: 1.1rem;
}
textarea {
width: 100%;
min-height: 150px;
padding: 15px;
border: 2px solid #e0e0e0;
border-radius: 10px;
font-size: 1rem;
resize: vertical;
transition: border 0.3s;
}
textarea:focus {
outline: none;
border-color: #6a11cb;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 25px;
}
.control-group {
flex: 1;
min-width: 200px;
}
.control-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #333;
}
.slider-container {
display: flex;
align-items: center;
gap: 10px;
}
input[type="range"] {
flex: 1;
height: 8px;
-webkit-appearance: none;
background: #e0e0e0;
border-radius: 5px;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 20px;
background: #6a11cb;
border-radius: 50%;
cursor: pointer;
}
.value-display {
min-width: 40px;
text-align: center;
font-weight: 600;
color: #6a11cb;
}
.voice-selector {
margin-bottom: 25px;
}
.voice-selector label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #333;
}
select {
width: 100%;
padding: 12px 15px;
border: 2px solid #e0e0e0;
border-radius: 10px;
font-size: 1rem;
background-color: white;
cursor: pointer;
}
.buttons {
display: flex;
justify-content: center;
gap: 15px;
flex-wrap: wrap;
}
button {
padding: 12px 25px;
border: none;
border-radius: 50px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s;
}
.play-btn {
background: linear-gradient(to right, #00b09b, #96c93d);
color: white;
padding: 12px 30px;
}
.pause-btn {
background: linear-gradient(to right, #f46b45, #eea849);
color: white;
}
.stop-btn {
background: linear-gradient(to right, #ff416c, #ff4b2b);
color: white;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
button:active {
transform: translateY(0);
}
button:disabled {
background: #cccccc;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.status {
text-align: center;
margin-top: 20px;
padding: 15px;
border-radius: 10px;
font-weight: 600;
}
.status.ready {
background-color: #e8f5e9;
color: #2e7d32;
}
.status.speaking {
background-color: #e3f2fd;
color: #1565c0;
}
.status.paused {
background-color: #fff3e0;
color: #ef6c00;
}
.footer {
text-align: center;
padding: 20px;
color: #777;
font-size: 0.9rem;
border-top: 1px solid #eee;
}
@media (max-width: 600px) {
.header h1 {
font-size: 1.8rem;
}
.content {
padding: 20px;
}
button {
padding: 10px 20px;
font-size: 0.9rem;
}
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<div class="header">
<h1><i class="fas fa-volume-up"></i> 文字轉(zhuǎn)語(yǔ)音播放器</h1>
<p>輸入文字,選擇語(yǔ)音,然后播放</p>
</div>
<div class="content">
<div class="text-input">
<label for="text-to-speak"><i class="fas fa-font"></i> 輸入要轉(zhuǎn)換的文字:</label>
<textarea
id="text-to-speak"
v-model="text"
placeholder="在這里輸入您想要轉(zhuǎn)換為語(yǔ)音的文字..."
></textarea>
</div>
<div class="controls">
<div class="control-group">
<label for="rate"><i class="fas fa-tachometer-alt"></i> 語(yǔ)速:</label>
<div class="slider-container">
<input
type="range"
id="rate"
min="0.5"
max="2"
step="0.1"
v-model="rate"
>
<span class="value-display">{{ rate }}x</span>
</div>
</div>
<div class="control-group">
<label for="pitch"><i class="fas fa-waveform"></i> 音調(diào):</label>
<div class="slider-container">
<input
type="range"
id="pitch"
min="0.5"
max="2"
step="0.1"
v-model="pitch"
>
<span class="value-display">{{ pitch }}</span>
</div>
</div>
</div>
<div class="voice-selector">
<label for="voice-select"><i class="fas fa-microphone"></i> 選擇語(yǔ)音:</label>
<select id="voice-select" v-model="selectedVoice">
<option v-for="voice in voices" :value="voice.name">
{{ voice.name }} ({{ voice.lang }})
</option>
</select>
</div>
<div class="buttons">
<button class="play-btn" @click="speak" :disabled="isSpeaking || !text">
<i class="fas fa-play"></i> {{ isPaused ? '繼續(xù)' : '播放' }}
</button>
<button class="pause-btn" @click="pause" :disabled="!isSpeaking || isPaused">
<i class="fas fa-pause"></i> 暫停
</button>
<button class="stop-btn" @click="stop" :disabled="!isSpeaking && !isPaused">
<i class="fas fa-stop"></i> 停止
</button>
</div>
<div class="status" :class="statusClass">
<i :class="statusIcon"></i> {{ statusText }}
</div>
</div>
<div class="footer">
<p>使用Web Speech API實(shí)現(xiàn) | Vue 3文字轉(zhuǎn)語(yǔ)音應(yīng)用</p>
</div>
</div>
</div>
<script>
const { createApp, ref, onMounted, computed, watch } = Vue;
createApp({
setup() {
const text = ref('歡迎使用Vue文字轉(zhuǎn)語(yǔ)音播放器!這是一個(gè)演示應(yīng)用,您可以輸入任何文字并轉(zhuǎn)換為語(yǔ)音播放。');
const rate = ref(1);
const pitch = ref(1);
const voices = ref([]);
const selectedVoice = ref('');
const isSpeaking = ref(false);
const isPaused = ref(false);
const synth = window.speechSynthesis;
// 計(jì)算狀態(tài)顯示
const statusText = computed(() => {
if (isSpeaking.value && !isPaused.value) return '正在播放語(yǔ)音...';
if (isPaused.value) return '語(yǔ)音已暫停';
if (!text.value) return '請(qǐng)輸入要轉(zhuǎn)換的文字';
return '準(zhǔn)備就緒,點(diǎn)擊播放按鈕開(kāi)始';
});
const statusClass = computed(() => {
if (isSpeaking.value && !isPaused.value) return 'speaking';
if (isPaused.value) return 'paused';
return 'ready';
});
const statusIcon = computed(() => {
if (isSpeaking.value && !isPaused.value) return 'fas fa-play-circle';
if (isPaused.value) return 'fas fa-pause-circle';
return 'fas fa-check-circle';
});
// 獲取可用的語(yǔ)音列表
const loadVoices = () => {
const availableVoices = synth.getVoices();
voices.value = availableVoices;
// 默認(rèn)選擇中文語(yǔ)音
if (availableVoices.length > 0) {
const chineseVoice = availableVoices.find(voice =>
voice.lang.includes('zh') || voice.lang.includes('CN')
);
selectedVoice.value = chineseVoice ? chineseVoice.name : availableVoices[0].name;
}
};
// 初始化語(yǔ)音
onMounted(() => {
// 某些瀏覽器需要延遲加載語(yǔ)音列表
if (synth.onvoiceschanged !== undefined) {
synth.onvoiceschanged = loadVoices;
}
loadVoices();
});
// 播放語(yǔ)音
const speak = () => {
if (isPaused.value) {
// 如果已暫停,恢復(fù)播放
synth.resume();
isPaused.value = false;
return;
}
if (isSpeaking.value) {
// 如果正在播放,先停止
synth.cancel();
}
if (!text.value) return;
const utterance = new SpeechSynthesisUtterance(text.value);
utterance.rate = rate.value;
utterance.pitch = pitch.value;
// 設(shè)置選定的語(yǔ)音
const voice = voices.value.find(v => v.name === selectedVoice.value);
if (voice) {
utterance.voice = voice;
}
utterance.onstart = () => {
isSpeaking.value = true;
isPaused.value = false;
};
utterance.onend = () => {
isSpeaking.value = false;
isPaused.value = false;
};
utterance.onerror = () => {
isSpeaking.value = false;
isPaused.value = false;
};
synth.speak(utterance);
};
// 暫停語(yǔ)音
const pause = () => {
if (isSpeaking.value && !isPaused.value) {
synth.pause();
isPaused.value = true;
}
};
// 停止語(yǔ)音
const stop = () => {
synth.cancel();
isSpeaking.value = false;
isPaused.value = false;
};
return {
text,
rate,
pitch,
voices,
selectedVoice,
isSpeaking,
isPaused,
statusText,
statusClass,
statusIcon,
speak,
pause,
stop
};
}
}).mount('#app');
</script>
</body>
</html>
功能說(shuō)明
這個(gè)Vue文字轉(zhuǎn)語(yǔ)音應(yīng)用具有以下功能:
1.文本輸入:用戶可以輸入或粘貼需要轉(zhuǎn)換為語(yǔ)音的文字
2.語(yǔ)音調(diào)節(jié):
- 語(yǔ)速控制(0.5x - 2x)
- 音調(diào)控制(0.5 - 2)
3.語(yǔ)音選擇:從瀏覽器支持的語(yǔ)音列表中選擇喜歡的語(yǔ)音
4.播放控制:播放/暫停/停止功能
5.狀態(tài)顯示:實(shí)時(shí)顯示當(dāng)前播放狀態(tài)
6.響應(yīng)式設(shè)計(jì):適配各種屏幕尺寸
使用說(shuō)明
- 在文本框中輸入或粘貼您想要轉(zhuǎn)換為語(yǔ)音的文字
- 根據(jù)需要調(diào)整語(yǔ)速和音調(diào)
- 從下拉菜單中選擇喜歡的語(yǔ)音(支持中文)
- 點(diǎn)擊播放按鈕開(kāi)始語(yǔ)音轉(zhuǎn)換
- 使用暫停和停止按鈕控制播放過(guò)程
這個(gè)應(yīng)用使用了現(xiàn)代瀏覽器的Web Speech API,在Chrome、Edge等主流瀏覽器中都能良好運(yùn)行。
到此這篇關(guān)于基于Vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音播放功能的示例代碼的文章就介紹到這了,更多相關(guān)Vue文字轉(zhuǎn)語(yǔ)音播放內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用drag與drop實(shí)現(xiàn)拖拽的示例代碼
本篇文章主要介紹了vue使用drag與drop實(shí)現(xiàn)拖拽的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
Vue3使用Swiper實(shí)現(xiàn)輪播圖示例詳解
這篇文章主要為大家介紹了Vue3使用Swiper實(shí)現(xiàn)輪播圖示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Vue3實(shí)現(xiàn)通過(guò)axios來(lái)讀取本地json文件
這篇文章主要介紹了Vue3實(shí)現(xiàn)通過(guò)axios來(lái)讀取本地json文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
uniapp仿微信聊天界面效果實(shí)例(vue3組合式版本)
這篇文章主要介紹了uniapp仿微信聊天界面的相關(guān)資料,這里提及了一個(gè)時(shí)間工具包timeMethod.js,該工具包可能提供了一系列時(shí)間處理的功能,如格式化日期、計(jì)算時(shí)間差等,以便在消息格式中正確展示時(shí)間信息,使用此類(lèi)工具包可以大大提高開(kāi)發(fā)效率,需要的朋友可以參考下2024-10-10
Vue實(shí)現(xiàn)計(jì)數(shù)器案例
這篇文章主要為大家詳細(xì)介紹了Vue計(jì)數(shù)器案例的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
vue導(dǎo)出excel的兩種實(shí)現(xiàn)方式代碼
這篇文章主要給大家介紹了關(guān)于vue導(dǎo)出excel的兩種實(shí)現(xiàn)方式,在項(xiàng)目中我們可能會(huì)碰到導(dǎo)出Excel文件的需求,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下2023-08-08

