俗話說的好,一天一蘋果,醫生遠離我
一天一 JS,What the f*ck JavaScript?
small steps every day - 記錄著新手村日記
語音輸出(speech synthesis)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Speech Synthesis</title>
<link href='https://fonts.googleapis.com/css?family=Pacifico' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="voiceinator">
<h1>The Voiceinator 5000</h1>
<select name="voice" id="voices">
<option value="">Select A Voice</option>
</select>
<label for="rate">Rate:</label>
<input name="rate" type="range" min="0" max="3" value="1" step="0.1">
<label for="pitch">Pitch:</label>
<input name="pitch" type="range" min="0" max="2" step="0.1">
<textarea name="text">Hello! I love JavaScript ?</textarea>
<button id="stop">Stop!</button>
<button id="speak">Speak</button>
</div>
<script>
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
</script>
</body>
</html>
首先,我們先將變數中的 msg 設定 text 值,也就是聲音要講的文字內容,在抓到值之前我們可以先看一下 SpeechSynthesisUtterance
裡面存放著什麼
//SpeechSynthesisUtterance {text: "", lang: "", voice: null, volume: -1, rate: -1, …}
透過 querySelector
抓取文字方塊內的 value
,並存進到上方的 text 之中
msg.text = document.querySelector('[name="text"]').value;
這時候就可以看到原本的 SpeechSynthesisUtterance
中的 text
值已經被更新了!
<script>
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
msg.text = document.querySelector('[name="text"]').value;
//SpeechSynthesisUtterance {text: "Hello! I love JavaScript ?", lang: "", voice: null, volume: -1, rate: -1, …}
</script>
再來我們來將 speechSynthesis
加上監聽事件 onvoiceschanged
並觸發populateVoices
方法,透過 SpeechSynthesis.getVoices()
取得包含所有物件的陣列,並將資料加入下拉式選單 Dropdown
SpeechSynthesis: voiceschanged event:https://tinyurl.com/y24evh2v
SpeechSynthesis.getVoices():https://tinyurl.com/ybxxro7q
<script>
// 上略
speechSynthesis.addEventListener('voiceschanged', populateVoices);
function populateVoices() {
voices = this.getVoices();
voicesDropdown.innerHTML = voices
.filter(voice => voice.lang.includes('en'))
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
.join('');
}
</script>
接下來來將剛剛加入的下拉式選單與聲音連動起來吧!透過陣列尋找如果現在我們選擇的聲音資料與API那端的相符,就會以那個聲音觸發 toggle
方法
<script>
// 上略
voicesDropdown.addEventListener('change', setVoice);
function setVoice() {
msg.voice = voices.find(voice => voice.name === this.value);
toggle();
}
</script>
toogle
方法就單純許多,只是控制先執行取消發生、再執行說話
SpeechSynthesis.cancel():https://tinyurl.com/yysl5zxs
SpeechSynthesis.speak():https://tinyurl.com/yykz4obn
<script>
// 上略
function toggle(startOver = true) {
speechSynthesis.cancel();
if (startOver) {
speechSynthesis.speak(msg);
}
}
</script>
再來調整發音速度與音調的部分
<script>
// 上略
options.forEach(option => option.addEventListener('change', setOption));
function setOption() {
//console.log(this.name, this.value);
msg[this.name] = this.value;
toggle();
}
</script>
最後就將按鈕觸發 click
來播放、停止說話,來控制 toggle
就可以控制說話惹w
<script>
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
msg.text = document.querySelector('[name="text"]').value;
speechSynthesis.addEventListener('voiceschanged', populateVoices);
function populateVoices() {
voices = this.getVoices();
voicesDropdown.innerHTML = voices
.filter(voice => voice.lang.includes('en'))
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
.join('');
}
voicesDropdown.addEventListener('change', setVoice);
function setVoice() {
msg.voice = voices.find(voice => voice.name === this.value);
toggle();
}
function toggle(startOver = true) {
speechSynthesis.cancel();
if (startOver) {
speechSynthesis.speak(msg);
}
}
options.forEach(option => option.addEventListener('change', setOption));
function setOption() {
console.log(this.name, this.value);
msg[this.name] = this.value;
toggle();
}
speakButton.addEventListener('click', toggle);
stopButton.addEventListener('click', () => toggle(false));
</script>
就大功告成啦!
<script>
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
msg.text = document.querySelector('[name="text"]').value;
speechSynthesis.addEventListener('voiceschanged', populateVoices);
function populateVoices() {
voices = this.getVoices();
voicesDropdown.innerHTML = voices
.filter(voice => voice.lang.includes('en'))
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
.join('');
}
voicesDropdown.addEventListener('change', setVoice);
function setVoice() {
msg.voice = voices.find(voice => voice.name === this.value);
toggle();
}
function toggle(startOver = true) {
speechSynthesis.cancel();
if (startOver) {
speechSynthesis.speak(msg);
}
}
options.forEach(option => option.addEventListener('change', setOption));
function setOption() {
console.log(this.name, this.value);
msg[this.name] = this.value;
toggle();
}
speakButton.addEventListener('click', toggle);
stopButton.addEventListener('click', () => toggle(false));
</script>
本刊同步於個人網站:http://chestertang.site/
本次範例程式碼原作者來源:https://tinyurl.com/yavm5f5n