前几天完成了一个需求,在网页中完成鼠标指向哪里,就用语音读出所指的文本。如果是按钮、链接、文本输入框,则还还要给出是什么的提醒。同时针对大段的文本,不能整段的去读,要按照标点符号进行断句处理。 重点当然就是先获取到当前标签上的文本,再把文本转化成语音即可。 标签朗读 这个很简单了,只用根据当前是什么标签,给出提示即可。 // 标签朗读文本 var tagTextConfig = { 'a': '链接', 'input[text]': '文本输入框', 'input[password]': '密码输入框', 'button': '按钮', 'img': '图片' }; 还有需要朗读的标签,继续再添加即可。 然后根据标签,返回前缀文本即可。 /** * 获取标签朗读文本 * @param {HTMLElement} el 要处理的HTMLElement * @returns {String} 朗读文本 */ function getTagText(el) { if (!el) return ''; var tagName = el.tagName.toLowerCase(); // 处理input等多属性元素 switch (tagName) { case 'input': tagName += '[' + el.type + ']'; break; default: break; } // 标签的功能提醒和作用应该有间隔,因此在最后加入一个空格 return (tagTextConfig[tagName] || '') + ' '; } 获取完整的朗读文本就更简单了,先取标签的功能提醒,再取标签的文本即可。 文本内容优先取 title 其次 alt 最后 innerText。 /** * 获取完整朗读文本 * @param {HTMLElement} el 要处理的HTMLElement * @returns {String} 朗读文本 */ function getText(el) { if (!el) return ''; return getTagText(el) + (el.title || el.alt || el.innerText || ''); } 这样就可以获取到一个标签的功能提醒和内容的全部带朗读文本了。 正文分隔 接下来要处理的就是正文分隔了,在这个过程中,踩了不少坑,走了不少弯路,好好记录一下。 首先准备了正文分隔的配置: // 正文拆分配置 var splitConfig = { // 内容分段标签名称 unitTag: 'p', // 正文中分隔正则表达式 splitReg: /[,;,;。]/g, // 包裹标签名 wrapTag: 'label', // 包裹标签类名 wrapCls: 'speak-lable', // 高亮样式名和样式 hightlightCls: 'speak-help-hightlight', hightStyle: 'background: #000!important; color: #fff!important' }; 最开始想的就是直接按照正文中的分隔标点符号进行分隔就好了呀。 想法如下: 获取段落全部文本 使用 split(分隔正则表达式) 方法将正文按照标点符号分隔成小段 每个小段用标签包裹放回去即可 然而理想很丰满,现实很骨感。 两个大坑如下: split 方法进行分隔,分隔后分隔字符就丢了,也就是说把原文的一些标点符号给弄丢了。 如果段落内还存在其他标签,而这个标签内部也正好存在待分隔的标点符号,那包裹分段标签时直接破换了原标签的完整性。 关于第一个问题,丢失标点的符号,考虑过逐个标点来进行和替换 split 分隔方法为逐个字符循环来做。 前者问题是原本一次完成的工作分成了多次,效率太低。第二种感觉效率更低了,分隔本来是很稀疏的,但是却要变成逐个字符出判断处理,更关键的是,分隔标点的位置要插入包裹标签,会导致字符串长度变化,还要处理下标索引。代码是机器跑的,或许不会觉得烦,但是我真的觉得好烦。如果这么干,或许以后哪个AI或者同事看到这样的代码,说不定会说“这真是个傻xxxx”。 第二个问题想过很多办法来补救,如先使用正则匹配捕获内容中成对的标签,对标签内部的分隔先处理一遍,然后再处理整个的。 想不明白问题二的,可参考一下待分隔的段落:
这是一段测试文本,这里有个链接。您好,可以点击此处进行跳转还有其他内容其他内容容其他内容容其他内容,容其他内容。 如先使用/<((\w+?)>)(.+?)<\/\2(?=>)/g 正则,依次捕获段落内被标签包裹的内容,对标签内部的内容先处理。 但是问题又来了,这么处理的都是字符串,在js中都是基本类型,这些操作进行的时候都是在复制的基础上进行的,要修改到原字符串里去,还得记录下原本的开始结束位置,再将新的插进去。繁,还是繁,但是已经比之前逐个字符去遍历的好,正则捕获中本来就有了匹配的索引,直接用即可,还能接受。 但是这只是处理了段落内部标签的问题,段落内肯定还有很多文本是没有处理呢,怎么办? (责任编辑:admin) |