Web 文本朗读 60 行代码实现

武汉肺炎在中国大陆肆虐的两个月,在后方的大家都在家闷得难受。一开始还在网上时刻关注各种疫情新闻,久而久之头昏眼花,十分疲惫。

发哨人艾芬医生采访稿被封杀后,墙国网民再次群情激奋地力挺,把原文用各种文字、编码、平台记录下来,妥妥的“留取丹青照汗青”!

其中有个网友用一款 Google Chrome 文本朗读 (TTS) 扩展把原文读出来,并把朗读过程录成视频分享出来,让大家闭目养神中就能了解疫情真相~

作为一个 Google 重度用户,针对一个事情可以搜出太多网页可读,眼睛会非常累,一直想找个方便的文本朗读工具。但作为一个 Web 全栈工程师,跨平台兼容性又是深入骨髓的自觉,于是翻出前一阵扫过一眼的 Web Speech API,抄起键盘就是一把梭 ——

上述代码所用的语音合成 API 现代浏览器支持很好,能用它的都支持 ES 6,所以我们只需压缩代码不需转译,再包上 javascript: (() => { /* code */ })() 即可直接存在浏览器收藏栏,当个扩展按钮使用了 ——

javascript:!((e)=>{const voice=speechSynthesis.getVoices().find(({lang:e})=>e===navigator.language);function speak(e){const t=new SpeechSynthesisUtterance(e);t.voice=voice,speechSynthesis.speak(t)}function*walkRange(e){const t=document.createNodeIterator(e.commonAncestorContainer);for(var n;(n=t.nextNode())&&(e.intersectsNode(n)&&(yield n),n!==e.endContainer););}function getSelectedText(e){const t=self.getSelection().getRangeAt(0);if(t&&t+””&&(!e||e.contains(t.commonAncestorContainer)))return[…walkRange(t)].filter(({nodeType:e,parentNode:t})=>{if(3!==e)return;const{width:n,height:o}=t.getBoundingClientRect();return n&&o}).map(({nodeValue:e},n,{length:o})=>e.slice(0===n?t.startOffset:0,n===o-1?t.endOffset:1/0)).filter(e=>e.trim()).join(“”).trim()}document.addEventListener(“selectionchange”,()=>{const e=getSelectedText();e&&!speechSynthesis.speaking?speak(e):speechSynthesis.cancel()}),self.alert(“Selected Text will be speak out automatically”);})();

Data on support for the speech-synthesis feature across the major browsers from caniuse.com

代码中还有几个重要 API,列出来供大家参考 ——

  1. Selection Range
  2. Selection change 事件
  3. NodeIterator

最后,以艾芬医生的两句话与君共勉 ——

每个人还是要坚持自己独立的思想,因为要有人站出来说真话,必须要有人,这个世界必须要有不同的声音

早知道有今天,我管他批评不批评,『老子』到处说!


上一篇
安徒生童话:技术人的群聊 安徒生童话:技术人的群聊
加过技术群的同学想必听过一句话 —— 技术人不谈政治~ 不少群公告还直接明文规定 —— 不要讨论敏感话题! 最初我以为,大家真的不喜欢探讨政治,直到最近我所在的 FCC 成都社区遭受一次网络暴力…… 事件原文前两天我的一篇技术博文被
2020-04-01
下一篇
PWA 即刻上手 PWA 即刻上手
近两年国内前端界很流行小程序,但大多数人都不知道小程序很多概念是鹅厂“借鉴”自 Google 主导的 Progressive Web App(渐进式网页应用)标准 —— “独立”运行:在“系统正在运行的应用”列表中独立显示 本地缓存:页面
2019-10-31