diff --git a/23 - Speech Synthesis/README.md b/23 - Speech Synthesis/README.md new file mode 100644 index 0000000..c0140e4 --- /dev/null +++ b/23 - Speech Synthesis/README.md @@ -0,0 +1,93 @@ +# 23 Speech Synthesis 中文指南 + +> 本篇作者:©[大史快跑Dashrun](https://github.com/dashrun)——Chinasoft Frontend Developer + +> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 23 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*) + +> 创建时间:2017-09-20 +最后更新:2017-09-22 + +## 挑战任务 +初始文档`index-start.html`提供了一个阅读器,你需要完成如下编程任务: +1.使用相应的WebAPI接口获得浏览器支持的语言种类列表,并填充至页面的下拉菜单中,选择中文; +2.在文本域中输入对应语言的文字,点击`speak`按钮后浏览器会阅读输入的文字; +3.在浏览器阅读时,点击`stop`按钮,浏览器会停止阅读; +4.拖动`rate`和`pitch`滑块可改变阅读速度和音高。 + +## 实现效果 +![结果展示](https://github.com/dashrun/vanilla-javascript-30/blob/master/23%20-%20Speech%20Synthesis/effects.png) + +## 相关知识 +1.`SpeechSynthesisUtterance`接口 + 本接口用于设置阅读器阅读的配置参数,包括语言,阅读速度,语调等,实例化`SpeechSynthesisUtterance`后,可以通过为其属性赋值来完成参数配置,详细信息请直接参考MDN中的[SpeechSynthesisUtterance接口说明](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance)。 +2.`SpeechSynthesis`接口 + 本接口用于控制阅读器行为,包括获取浏览器支持的朗读语言,文本朗读,暂停,停止等,接口属性中定义有paused,speaking等只读属性来表明当前的状态,详细使用方式请参考MDN中的[SpeechSynthesis接口说明](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis)。 + +## 编程思路 + 本次编程任务使用相应接口的最基本功能即可实现,编程中根据挑战任务中的说明逐步实现即可。 + +## 过程指南 +1.取得`speechSynthesis`对象,并取得浏览器支持的朗读语言,将所有支持的选项动态添加至下拉列表 +```js +const synth = window.speechSynthesis; + +//将获取支持语言并添加至下拉列表的代码段封装在一个函数中 +function getSupportVoice() { + voices = synth.getVoices();//获取支持的语言 + for(i = 0; i < voices.length ; i++) { + var option = document.createElement('option'); + option.textContent = voices[i].name + ' (' + voices[i].lang + ')'; + + if(voices[i].default) { + option.textContent += ' -- DEFAULT'; + } + + option.setAttribute('data-lang', voices[i].lang); + option.setAttribute('data-name', voices[i].name); + voicesDropdown.appendChild(option); + } +} + +//经测试直接执行getSupportVoice()时无法获得预期效果,须由事件触发该函数。 +synth.addEventListener('voiceschanged', getSupportVoice); +``` +2.点击`speak`按钮后朗读(为方便说明,以下代码段与所提供的完成代码顺序不完全一致) +```js +//实例化配置对象 +const msg = new SpeechSynthesisUtterance(); + +//定义一段默认朗读内容 +msg.text = '你能说中文吗'; + +//点击speak按钮时阅读文字 +function speak() { + console.log(voicesDropdown.value); + synth.speak(msg); +} + +//将阅读函数绑定至`speak`按钮的点击事件上 +speakButton.addEventListener('click', speak); +``` +3.点击`stop`按钮停止朗读 +```js +//停止朗读 +function stopSpeak(){ + synth.cancel(); +} +//将停止朗读函数绑定至`stop`按钮的点击事件上 +stopButton.addEventListener('click', stopSpeak); +``` +4.参数配置可更改 +```js +//index-start.html中提供的选择器将返回rate值,pitch值以及阅读内容对应的DOM元素 + const options = document.querySelectorAll('[type="range"], [name="text"]'); +//将阅读参数赋值至msg的同名实例属性 +function paramChange(){ + msg[this.name] = this.value; +} +options.forEach(opt => opt.addEventListener('change', paramChange)); +``` + + + + diff --git a/23 - Speech Synthesis/effects.png b/23 - Speech Synthesis/effects.png new file mode 100644 index 0000000..d6f342a Binary files /dev/null and b/23 - Speech Synthesis/effects.png differ diff --git a/23 - Speech Synthesis/index-finished-Dashrun.html b/23 - Speech Synthesis/index-finished-Dashrun.html new file mode 100644 index 0000000..56affc8 --- /dev/null +++ b/23 - Speech Synthesis/index-finished-Dashrun.html @@ -0,0 +1,82 @@ + + + + + Speech Synthesis + + + + +
+ +

听说 5000

+ + + + + + + + + + + + + +
+ + + + + diff --git a/23 - Speech Synthesis/index-start.html b/23 - Speech Synthesis/index-start.html new file mode 100644 index 0000000..b909453 --- /dev/null +++ b/23 - Speech Synthesis/index-start.html @@ -0,0 +1,40 @@ + + + + + Speech Synthesis + + + + +
+ +

The Voiceinator 5000

+ + + + + + + + + + + + + +
+ + + + + diff --git a/23 - Speech Synthesis/style.css b/23 - Speech Synthesis/style.css new file mode 100644 index 0000000..86bd48e --- /dev/null +++ b/23 - Speech Synthesis/style.css @@ -0,0 +1,98 @@ +html { + font-size: 10px; + box-sizing: border-box; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body { + margin: 0; + padding: 0; + font-family: sans-serif; + background-color:#3BC1AC; + display:flex; + min-height: 100vh; + align-items: center; + + background-image: + radial-gradient(circle at 100% 150%, #3BC1AC 24%, #42D2BB 25%, #42D2BB 28%, #3BC1AC 29%, #3BC1AC 36%, #42D2BB 36%, #42D2BB 40%, transparent 40%, transparent), + radial-gradient(circle at 0 150%, #3BC1AC 24%, #42D2BB 25%, #42D2BB 28%, #3BC1AC 29%, #3BC1AC 36%, #42D2BB 36%, #42D2BB 40%, transparent 40%, transparent), + radial-gradient(circle at 50% 100%, #42D2BB 10%, #3BC1AC 11%, #3BC1AC 23%, #42D2BB 24%, #42D2BB 30%, #3BC1AC 31%, #3BC1AC 43%, #42D2BB 44%, #42D2BB 50%, #3BC1AC 51%, #3BC1AC 63%, #42D2BB 64%, #42D2BB 71%, transparent 71%, transparent), + radial-gradient(circle at 100% 50%, #42D2BB 5%, #3BC1AC 6%, #3BC1AC 15%, #42D2BB 16%, #42D2BB 20%, #3BC1AC 21%, #3BC1AC 30%, #42D2BB 31%, #42D2BB 35%, #3BC1AC 36%, #3BC1AC 45%, #42D2BB 46%, #42D2BB 49%, transparent 50%, transparent), + radial-gradient(circle at 0 50%, #42D2BB 5%, #3BC1AC 6%, #3BC1AC 15%, #42D2BB 16%, #42D2BB 20%, #3BC1AC 21%, #3BC1AC 30%, #42D2BB 31%, #42D2BB 35%, #3BC1AC 36%, #3BC1AC 45%, #42D2BB 46%, #42D2BB 49%, transparent 50%, transparent); + background-size:100px 50px; +} + + +.voiceinator { + padding:2rem; + width:50rem; + margin:0 auto; + border-radius:1rem; + position: relative; + background:white; + overflow: hidden; + z-index: 1; + box-shadow:0 0 5px 5px rgba(0,0,0,0.1); +} + +h1 { + width:calc(100% + 4rem); + margin: -2rem 0 2rem -2rem; + padding:.5rem; + background: #ffc600; + border-bottom: 5px solid #F3C010; + text-align: center; + font-size: 5rem; + font-weight: 100; + font-family: 'Pacifico', cursive; + text-shadow:3px 3px 0 #F3C010; + +} + +.voiceinator input, +.voiceinator button, +.voiceinator select, +.voiceinator textarea { + width: 100%; + display: block; + margin:10px 0; + padding:10px; + border:0; + font-size: 2rem; + background:#353535; + color:white; + outline:0; +} + +textarea { + height: 20rem; +} + +input[type="select"] { + +} + +.voiceinator button { + background:#ffc600; + border:0; + width: 49%; + float:left; + font-family: 'Pacifico', cursive; + margin-bottom: 0; + font-size: 2rem; + border-bottom: 5px solid #F3C010; + cursor:pointer; + position: relative; +} + +.voiceinator button:active { + top:2px; +} + +.voiceinator button:nth-of-type(1) { + margin-right: 2%; +} + diff --git a/README.md b/README.md index 0d6d9a6..73a4b78 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ No | Guide | Demo 19 | [Webcam Fun 指南](https://github.com/soyaine/JavaScript30/blob/master/19%20-%20Webcam%20Fun/README.md) | [网络摄像头及图片处理在线效果](https://github.com/soyaine/JavaScript30/blob/master/19%20-%20Webcam%20Fun/index-finished-Dashrun.html) 20 | [Speech Detection指南](https://github.com/soyaine/JavaScript30/blob/master/20%20-%20Speech%20Detection/README.md) | [Speech Detection效果](https://github.com/soyaine/JavaScript30/blob/master/20%20-%20Speech%20Detection/index-finished-Dashrun.html) 21 | [Geolocation指南](https://github.com/soyaine/JavaScript30/blob/master/21%20-%20Geolocation/README.md) | [Geolocation效果](https://github.com/soyaine/JavaScript30/blob/master/21%20-%20Geolocation/index-finished-Dashrun.html) -22 | Follow Along Link Highlighter | - +22 | [Follow Along Link Highlighter指南](https://github.com/soyaine/JavaScript30/blob/master/22%20-%20Follow%20Along%20Link%20Highlighter/README.md) | [Follow Along Link Highlighter效果](https://github.com/soyaine/JavaScript30/blob/master/22%20-%20Follow%20Along%20Link%20Highlighter/index-finished-Dashrun.html) 23 | Speech Synthesis | - 24 | Sticky Nav | - 25 | Event Capture, Propagation, Bubbling, and Once | - @@ -80,7 +80,7 @@ Name | Contribution [@DrakeXiang](https://github.com/DrakeXiang) | No.[11](https://github.com/soyaine/JavaScript30/tree/master/11%20-%20Custom%20Video%20Player) [@zzh466](http://github.com/zzh466) | Review [@Xing Liu](https://github.com/S1ngS1ng) | Review -[@大史快跑Dashrun](https://github.com/dashrun) | No.[16](https://github.com/soyaine/JavaScript30/tree/master/16%20-%20Mouse%20Move%20Shadow).[17](https://github.com/soyaine/JavaScript30/tree/master/17%20-%20Sort%20Without%20Articles).[18](https://github.com/soyaine/JavaScript30/tree/master/18%20-%20AddingUpTimesWithReduce).[19](https://github.com/soyaine/JavaScript30/blob/master/19%20-%20Webcam%20Fun).[20](https://github.com/soyaine/JavaScript30/tree/master/20%20-%20Speech%20Detection).[21](https://github.com/soyaine/JavaScript30/tree/master/21%20-%20Geolocation) +[@大史快跑Dashrun](https://github.com/dashrun) | No.[16](https://github.com/soyaine/JavaScript30/tree/master/16%20-%20Mouse%20Move%20Shadow).[17](https://github.com/soyaine/JavaScript30/tree/master/17%20-%20Sort%20Without%20Articles).[18](https://github.com/soyaine/JavaScript30/tree/master/18%20-%20AddingUpTimesWithReduce).[19](https://github.com/soyaine/JavaScript30/blob/master/19%20-%20Webcam%20Fun).[20](https://github.com/soyaine/JavaScript30/tree/master/20%20-%20Speech%20Detection).[21](https://github.com/soyaine/JavaScript30/tree/master/21%20-%20Geolocation).[22](https://github.com/soyaine/JavaScript30/tree/master/22%20-%20Follow%20Along%20Link%20Highlighter) [@缉熙Soyaine](https://github.com/soyaine) | No.[1](https://github.com/soyaine/JavaScript30/tree/master/01%20-%20JavaScript%20Drum%20Kit).[2](https://github.com/soyaine/JavaScript30/tree/master/02%20-%20JS%20%2B%20CSS%20Clock).[3](https://github.com/soyaine/JavaScript30/tree/master/03%20-%20CSS%20%Variables).[4](https://github.com/soyaine/JavaScript30/tree/master/04%20-%20Array%20Cardio%20Day%201).[5](https://github.com/soyaine/JavaScript30/blob/master/05%20-%20Flex%20Panel%20Gallery).[6](https://github.com/soyaine/JavaScript30/blob/master/06%20-%20Type%20Ahead).[7](https://github.com/soyaine/JavaScript30/tree/master/07%20-%20Array%20Cardio%20Day%202).[8](https://github.com/soyaine/JavaScript30/tree/master/08%20-%20Fun%20with%20HTML5%20Canvas).[9](https://github.com/soyaine/JavaScript30/blob/master/09%20-%20Dev%20Tools%20Domination).[10](https://github.com/soyaine/JavaScript30/blob/master/10%20-%20Hold%20Shift%20and%20Check%20Checkboxes/README.md).[12](https://github.com/soyaine/JavaScript30/tree/master/12%20-%20Key%20Sequence%20Detection/README.md).[13](https://github.com/soyaine/JavaScript30/blob/master/13%20-%20Slide%20in%20on%20Scroll/README.md).[14](https://github.com/soyaine/JavaScript30/tree/master/14%20-%20JavaScript%20References%20VS%20Copying) ## JOIN US