简介

网页文字语音阅读功能实现的核心是通过 网页语音 API 的SpeechSynthesis 接口是语音服务的控制接口;它可以用于获取设备上关于可用的合成声音的信息,开始、暂停语音,或除此之外的其他命令。

在定义了一些必要的变量后,我们用 SpeechSynthesis.getVoices()获取了一列可用的声音并且用它们生成一列可选表单,这样用户能够选择他们想要的声音。

inputForm.onsubmit 的内部操作中,我们用preventDefault()阻止了表单的提交,创建了一个从<input>文本框获取文本的新SpeechSynthesisUtterance实例,在<select>元素可选的声音设置成语音谈话的voice属性,然后通过SpeechSynthesis.speak() (en-US)方法开始语音播放。

图示

网页语音的语言类型是根据客户端本地浏览器类型,拥有不同的语言类型,网页文字的语音阅读可以在没有外网的情况下使用。

项目结构图

代码示例

index.html 完整代码示例


<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>语音文字阅读器</title><link rel="stylesheet" href="css/index.css">
</head>
<body><div class="container"><h1>语音文字阅读器</h1><button id="toggle-box" class="btn btn-toggle" type="button">阅读输入文本</button><div id="box" class="box"><h3>选择语音的语言类型:</h3><div class="select-container select-voices"><div class="select-title"><div class="select-content" tabindex="0" hidefocus="true"></div><i class="select-icon select-down"></i></div><ul class="select-items"></ul></div><textarea class="read-content" id="read-content" placeholder="请输入要阅读的内容"></textarea><button id="read-btn" class="btn read-btn" type="button">阅读</button><span class="close-box-btn" id="close-box-btn">&times;</span></div><main id="main" class="main"></main></div>
</body>
<script src="js/message.js"></script>
<script src="js/index.js"></script>
</html>

index.js 代码示例


function $(selector) {return document.querySelector(selector);
}
function $$(selector) {return document.querySelectorAll(selector);
}
HTMLElement.prototype.hasClass = function (className) {return new RegExp(" " + className + " ").test(' ' + this.className + ' ');
}
// 语言类型数组
let voices = [];
// 默认语言类型
let voice = "zh-CN";
const songs = [{name: "她不是真的爱我",singer: "白小白",imgName: "baixiaobai"},{name: "下雪的季节",singer: "本兮",imgName: "benxi"},{name: "今生他生",singer: "陈启泰",imgName: "chenqitai"},{name: "流着泪为你祝福",singer: "韩小薰",imgName: "hanxiaoxun"},{name: "真爱你的云",singer: "黄国俊",imgName: "huangguojun"},{name: "车站",singer: "李健",imgName: "lijian"},{name: "伤了心的女人怎么了",singer: "刘涛",imgName: "liutao"},{name: "画颜",singer: "魏新雨",imgName: "weixinyu"},{name: "祝你一路顺风",singer: "吴奇隆",imgName: "wuqilong"},{name: "回来我的爱",singer: "阳一",imgName: "yangyi"},{name: "绵阳印象",singer: "羽上轩",imgName: "yushangxuan"},{name: "滚蛋歌",singer: "张翰",imgName: "zhanghan"},{name: "烈火青春",singer: "张雨生",imgName: "zhangyusheng"},{name: "成都",singer: "赵雷",imgName: "zhaolei"},{name: "歌唱二小放牛郎",singer: "杨慧妍",imgName: "yanghuiyan"},{name: "我的唇吻不到我爱的人",singer: "王奕心",imgName: "wangyixin"},{name: "贝多芬的悲伤",singer: "萧风",imgName: "xiaofeng"},{name: "菊花爆满山",singer: "马博",imgName: "mabo"},{name: "一亿个伤心",singer: "蒙面哥",imgName: "mengmiange"},{name: "帝都",singer: "萌萌哒天团",imgName: "mengmengdatiantuan"},{name: "陪你一起变老",singer: "唐古",imgName: "tanggu"},{name: "我在前世约了你",singer: "唐古",imgName: "tanggu"},{name: "恋人心",singer: "魏新雨",imgName: "weixinyu"},{name: "新娘不是我",singer: "程响",imgName: "chengxiang"}
];
// 变量定义部分
const toggleBoxBtn = $("#toggle-box");
const closeBoxBtn = $("#close-box-btn");
const readBtn = $("#read-btn");
const box = $("#box");
const readContent = $("#read-content");
const main = $("#main");
// 获取阅读信息对象实例
let message = new SpeechSynthesisUtterance();
// console.log(message);
message.lang = voice;
songs.forEach(createPopBox);
/*** 创建每一块* @param {*} item */
function createPopBox(item){const boxItem = document.createElement('div');boxItem.classList.add('box');boxItem.innerHTML = `<p>我是${ item.singer },我唱的《${ item.name }》。</p>`;main.appendChild(boxItem);
}
// 点击每一列
const children = main.querySelectorAll('.box');
children.forEach(box => {box.addEventListener('click',() => {children.forEach((child) => {child.classList.remove('active');});box.classList.add('active');setMessageText(box.querySelector('p').innerText.trim());speakMessage();});
});
/*** 设置文本* @param {*} text */
function setMessageText(text){return message.text = text;
}
/*** 获取阅读语言类型*/
function getVoices() {voices = speechSynthesis.getVoices();// console.log(voices);
}
/*** 加载下拉选项* @param {*} selectContainer */
function loadSelect(selectContainer) {const selectListItem = selectContainer.querySelector('.select-items');selectListItem.innerHTML = "";voices.forEach(voice => {const voiceItem = document.createElement('div');voiceItem.classList.add('select-option');voiceItem.setAttribute('data-value', voice.lang);voiceItem.innerHTML = voice.name + '(' + voice.lang + ")";selectListItem.appendChild(voiceItem);});const label = voices.find(_ => voice === _.lang).name + '(' + voice + ")";setDefaultSelectValue(selectContainer.querySelector('.select-content'),label);
}
/*** 设置选择下拉选项值* @param {*} el * @param {*} label */
function setDefaultSelectValue(el, label) {return el.innerHTML = label;
}
/*** 下拉逻辑处理* @param {*} selectContainer */
function selectHandle(selectContainer) {let selectFlag = false;let showSelect = function (el, bool) {if (bool) {if (el.lastElementChild.hasClass('select-down')) {el.lastElementChild.classList.replace('select-down', 'select-up');} else {el.lastElementChild.classList.add('select-up');}el.nextElementSibling.style.display = "block";} else {if (el.lastElementChild.hasClass('select-up')) {el.lastElementChild.classList.replace('select-up', 'select-down');} else {el.lastElementChild.classList.add('select-down');}el.nextElementSibling.style.display = "none";}}selectContainer.firstElementChild.onclick = function () {selectFlag = !selectFlag;showSelect(this, selectFlag);};let isBlur = false;let selectOptionArr = [].slice.call(selectContainer.lastElementChild.children);selectOptionArr.forEach((item) => {item.onclick = function () {selectFlag = false;isBlur = true;let select_content = this.innerHTML;this.parentElement.previousElementSibling.firstElementChild.innerHTML = select_content;selectOptionArr.map((opt) => {opt.classList.remove('select-this');});message.voice = voices.find(voice => voice.lang === this.getAttribute('data-value'));this.classList.add('select-this');showSelect(this.parentElement.previousElementSibling, false);}});selectContainer.firstElementChild.firstElementChild.onblur = function () {setTimeout(() => {if (!isBlur) {selectFlag = false;showSelect(this.parentElement, false);} else {isBlur = false;}}, 200)};
}
/*** 阅读输入的文本*/
function speakMessage() {return speechSynthesis.speak(message);
}
// 加载语言类型
getVoices();
// 事件监听部分
speechSynthesis.addEventListener('voiceschanged', getVoices);
toggleBoxBtn.addEventListener('click',() => {box.classList.add('show');
});
closeBoxBtn.addEventListener('click',() => {box.classList.remove('show');
});
readBtn.addEventListener('click',() => {const content = readContent.value;if(!content.trim())return $message.warning("请输入要阅读的文本内容!");setMessageText(content);speakMessage();
});
setTimeout(() => {loadSelect($('.select-voices'));selectHandle($('.select-voices'));
}, 1000);

message.js 代码示例

// 消息框类型
const typeMap = {success:"success",info:"info",warning:"warning",error:"error"
};
function isFunction(value){return typeof value === 'function';
}
function isDom(el) {return typeof HTMLElement === 'object' ? el instanceof HTMLElement : el && typeof el === 'object' && el.nodeType === 1 && typeof el.nodeName === 'string' || el instanceof HTMLCollection || el instanceof NodeList;
}
function addMessageStyle() {var cssText = `.ew-message {min-width: 300px;border: 1px solid #ebeef5;position: fixed;left: 50%;background-color: #edf2fc;transform: translateX(-50%);display: flex;align-items: center;padding: 10px 15px;overflow: hidden;transition: transform .4s;border-radius: 4px;top: 25px;z-index: 10001;}.ew-message .ew-message-close {position: absolute;top: 50%;right: 15px;transform: translateY(-50%);cursor: pointer;color: #C0C4CC;font-size: 16px;}.ew-message>.ew-message-close:hover,.ew-message>.ew-message-close:active {color: #909399;}.ew-message-info p {color: #909399;line-height: 1;font-size: 14px;}.ew-message-center {justify-content: center;}.ew-message-success {background-color: #e1f3d8;border-color: #e1f3d8;}.ew-message-success p {color: #67c23a;}.ew-message-warning {background-color: #fdfce6;border-color: #faecd8;}.ew-message-warning p {color: #e6a23c;}.ew-message-error {background-color: #fef0f0;border-color: #fde2e2;}.ew-message-error p {color: #f56c6c;}`;function styleInject(css, ref) {if (ref === void 0) ref = {};var insertAt = ref.insertAt;if (!css || typeof document === 'undefined') return;var head = document.head || document.getElementsByTagName('head')[0];var style = document.createElement('style');style.type = "text/css";if (insertAt === 'top') {if (head.firstChild) {head.insertBefore(style, head.firstChild)} else {head.appendChild(style);}} else {head.appendChild(style);}if (style.styleSheet) {style.styleSheet.cssText = css;} else {style.appendChild(document.createTextNode(css));}}styleInject(cssText);
}
addMessageStyle();
let $message = {};
window['$message'] = $message= function(option){return new Message(option);
}
for(let key in typeMap){window.$message[key] =$message[key] = function(option){let messageOption = {content:"内容",center:false,type:key,closeTime:600,showClose:true}if(typeof option === 'string'){messageOption.content = option;}else if(typeof option === 'object' && !!option){messageOption = Object.assign(messageOption,option);}return new Message(messageOption);}
}function Message(option){let messageOption = {content:"内容",center:false,type:"info",closeTime:600,showClose:true}if(typeof option === 'string'){messageOption.content = option;}else if(typeof option === 'object' && !!option){messageOption = Object.assign(messageOption,option);}this.render(messageOption);}
Message.prototype.render = function(messageOption){if (messageOption.closeTime <= 0 && !messageOption.showClose) messageOption.showClose = true;let closeBtn = null;//设置关闭按钮相关if (messageOption.showClose) {closeBtn = document.createElement('i');closeBtn.classList.add('ew-message-close');closeBtn.innerHTML = '&times;';}document.body.appendChild(this.create(messageOption, closeBtn));let messageElement = document.querySelectorAll('.ew-message');this.setTop(messageElement);// 关闭时间大于0时关闭提示框if (messageOption.closeTime > 0) {this.close(messageOption.el, messageOption.closeTime);}// 点击关闭消息提示框if (messageOption.closeBtnEl) {messageOption.closeBtnEl.onclick = (e) => {this.close(e.currentTarget.parentElement, 0);}}
}
Message.prototype.setTop = function (messageElement) {if(!messageElement || !messageElement.length)return;// 每个高度是一样的,所以随便获取一个即可const height = messageElement.length ? messageElement[0].offsetHeight : messageElement.offsetHeight;for (let i = 0, len = messageElement.length; i < len; i++) {messageElement[i].setAttribute('style', 'top:' + (25 * (i + 1) + height * i) + 'px;');}
}
Message.prototype.create = function(messageOption,closeBtn){let element = document.createElement('div');element.className = `ew-message ew-message-${messageOption.type}`;if (messageOption.center) element.classList.add('ew-message-center');const p = document.createElement('p');p.innerHTML = messageOption.content;element.appendChild(p);if (closeBtn) element.appendChild(closeBtn);messageOption.el = element;messageOption.closeBtnEl = closeBtn;return element;
}
Message.prototype.close = function(messageElement, time){setTimeout(() => {if (messageElement && messageElement.length) {[].slice.call(messageElement).forEach((item) => {if (isDom(item) && isDom(item.parentElement) && isFunction(item.parentElement.removeChild)) {item.parentElement.removeChild(item);}})} else {if (isDom(messageElement) && isDom(messageElement.parentElement) && isFunction(messageElement.parentElement.removeChild)) {messageElement.parentElement.removeChild(messageElement);}}this.setTop(document.querySelectorAll('.ew-message'));}, time * 10);
}

样式以及完整代码下载

通过js实现对文本内容语音阅读-网页制作文档类资源-CSDN下载HTML5中和WebSpeech相关的API实际上有两类,一类是“语音识别(SpeechReco更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/weixin_40986713/81098149

html5 | 通过js实现对网页文本内容语音朗读 | 教程相关推荐

  1. php写语音朗读,详解在网页上通过JS实现文本的语音朗读

    摘要: 语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的.或外部输入的文字信息转变为可以听得懂的.流利的口语输出的技术. 1.接口定义 http://tts.baidu.com/tex ...

  2. 语音朗读html的源码,详解在网页上通过JS实现文本的语音朗读

    摘要: 语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的.或外部输入的文字信息转变为可以听得懂的.流利的口语输出的技术. 1.接口定义 http://tts.baidu.com/tex ...

  3. android 文字选中朗读,Android开发之文本内容自动朗读功能实现方法

    本文实例讲述了Android开发之文本内容自动朗读功能实现方法.分享给大家供大家参考,具体如下: Android提供了自动朗读支持.自动朗读支持可以对指定文本内容进行朗读,从而发生声音:不仅如此,An ...

  4. android的发音功能实现,Android开发之文本内容自动朗读功能实现方法

    本文实例讲述了Android开发之文本内容自动朗读功能实现方法.分享给大家供大家参考,具体如下: Android提供了自动朗读支持.自动朗读支持可以对指定文本内容进行朗读,从而发生声音:不仅如此,An ...

  5. html 文字输出语音,网页上通过JS实现文本的语音朗读

    1.接口定义 http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=2&text=你要转换的文字 参数说明: lan=zh:语 ...

  6. c语言读取网页文本内容,从文本文件中读取数据

    请问如何用c语言从txt文件中读取数据? 请问如何用c语言从txt文件中读取数据? 就是用空格分开的数据,例如:12//其中的in.txt就是你要读取数据的文件,当然把它和程序放在同一目录 - #in ...

  7. java抓取网页标题内容_[Java教程]java 网页页面抓取标题和正文

    [Java教程]java 网页页面抓取标题和正文 0 2014-07-10 09:01:30 import java.io.BufferedReader;import java.io.IOExcept ...

  8. 主攻ASP.NET.4.5.1 MVC5.0之重生:Web项目语音朗读网页文本,简单语音提示浏览状态

    第一步 添加SpeechLib.dll 下载SpeechLib.dll: 在项目中并且引用DLL using SpeechLib; using System.Threading; 第二步 调用并使用 ...

  9. HTML5网页文本内容

    1 标题文字的建立 1.1 标题文字的建立   HTML文档中的标题由<h1>到<h6>元素来定义,其中<h1>代表一级标题,级别最高,文字也最大,其它标题元素依次 ...

最新文章

  1. LeetCode简单题之检查某单词是否等于两单词之和
  2. 二. 主流视频编码标准的发展
  3. js检测是否安装了flash插件
  4. Android7.0 PowerManagerService(3) 核心函数updatePowerStateLocked的主要流程
  5. Java Lambda表达式的使用
  6. 十进制转任意进制-数论
  7. disabled与enabled是什么?disabled与enabled属性详解
  8. Mybatis plus 修改密码
  9. found zsh 所有命令在终端失效
  10. 世界读书日送你畅销好书!前所未有4折购书福利
  11. HDU 6078 Wavel Sequence
  12. ——大牛很通俗地介绍《信号与系统》
  13. 使用支付宝支付出现问题:交易订单处理失败 请稍后再试 ALI38173
  14. before和after怎么区分_before和after区别 关于before和after
  15. ubuntu18分辨率变低,无法调整,最高只有1024*768
  16. vue3之常范低级错误の错误指南
  17. 开发者出海跨境收款——如何完美解决限额问题?
  18. 数据分析团队正成为手游公司的标配,但我为什么说解散他
  19. 每天学习Java一点点
  20. SRRC认证全面解析

热门文章

  1. 描写火车站场景_描写春运火车拥挤的作文_火车站上
  2. Kejin Player (概率DP)hdu6656
  3. iOS逆向工程-工具篇
  4. 3月下旬到5月中旬之前采制的茶叶
  5. 这所北京计算机类大学,改考408了!北京信息科技大学
  6. 2021全年营收净利润双增,李宁财报透露哪些确定与不定?
  7. 用递归方式写斐布拉契数列的坏处
  8. 第5部分- Linux ARM汇编 ARM 架构细节
  9. mysql mmm 虚拟ip不通_mysql-mmm故障解决一例
  10. Python第三方库之MedPy