网页中文本朗读功能开发实现分享

网页中文本朗读功能开发实现分享,第1张

网页中文本朗读功能开发实现分享

前几天完成一个需求,在网页中完成鼠标背面的时候,通过语音读出引用的文字。如果它是一个按钮,一个链接,或者一个输入到框中的文本,那么借用应该给出它是什么的提示。同时,对于大段文字,不要整段阅读,要根据标签停止断句。

当然,重点是先获取当前标签上的文本,然后将文本转换成语音。

标签背诵

那很简单。按照现在的标签是什么给个提醒就行了。

//标签背诵文本

vartagTextConfig={

a':'链接',

输入[文本]':'文本被输入到框中',

输入[密码]':'瘦码输入到框中',

按钮':'按钮',

  'img':'图片'Img':'图片'

};

借用需要背诵的标签,不断增加。

然后按照标签返回前缀文本。

/**

*获取标记背诵文本

*@param{HTMLElement}el要处理的HTMLElement

*@returns{String}背诵课文

*/

函数getTagText(el){

如果(!el)返回“”;

vartagName=El.tagName.tolowercase();

//处置输入等多属性元素

开关(标记名){

案例“输入”:

标记名+='['+El.type+']';

打破;

默认值:

打破;

}

//标签的作用是提示战争要有距离,所以我一开始是参与一个空网格。

return(tagTextConfig[tagName]||'')+'';

}

想得到一篇好的背诵课文更简单,先有标签的功能提示,再有标签的正文。

首先是内容,其次是标题,然后是alt,最初是innerText。

/**

*获得好的阅读文本。

*@param{HTMLElement}el要处理的HTMLElement

*@returns{String}背诵课文

*/

函数getText(el){

如果(!el)返回“”;

returngetTagText(El)+(El.title||El.alt||El.innertext||'');

}

这样就可以得到一个本地的背诵文本,具有标签的功能,提示战争的内容。

单独的评论

接下来要处理的是注释的分离。在那个过程中,我踩了很多坑,走了很多直路,所以做好记录。

最后,准备了一个单独的注释设置:

//注释拆分赋值

varsplitConfig={

//内容片段的名称。

unitTag:'p',

//注释平面分隔的正则表达式

splitReg:/[,;,;。]/g,

//包裹标签签名

wrapTag:“标签”,

//宗地标注分类名称

包装:“可说话”,

//下面这几种风格都是以格斗风格出名的。

高光:说话-救命-高光,

hightStyle:'背景:#000!重要;颜色:#fff!'重要'

};

首先要读的是根据标注中的分离标记间接停止分离。

阅读以下内容:

获取段放置本地文本。

Split(SplitRegularExpression)方法用于根据标准标记将注释分成小段。

把每一小部分用标签包好,然后放好。

但是幻想很丰满,理想很骨感。

下面两个大坑:

拆分法停止了拆分,拆分后的字被捡出,也就是陶在这篇文章里捡出了一些标准的记号。

如果段内借用了另一个标签,而那个标签内的标签又恰好有要分离的标签,那么宗地段标签时间就会改变这个标签的完整性。

第一次成就,失去了目标的印记,想着一个一个的停止战斗,交换分裂的方法,一个一个的做。

前一种成绩是原本一次性完成的事情,分红多次,服从性太低。第二种感觉服从性较低,分隔很密,但会导致对人物的逐一判断和处置。更重要的是,分离目标的位置要插入到包裹标签中,这样会导致字符串的变化较小,下标索引要处理掉。代码是机械运行的,所以我大概不觉得很烦,但是我真的觉得很烦。如果是,大概是哪个现任AI同事看到那段代码,道就不会说“那真是傻子xxxx”。

有很多方法可以弥补第二个成就,比如先通过正则婚姻捕捉到内容中的成对标签,先处理掉标签的内部分隔,然后全部处理掉。

如果你没有大白分二,请参考要分开的段位:

那是一个测试文本,那里有一个链接。你好,你可以点击这里停止跳转。借其他内容,其他内容,其他内容,其他内容。

使用/<((w+?)>)(.+?)</2(?=>)/g正则化,依次抓取片段中标签包裹的内容,先处置标签内部的内容。

但是结果又走了,所以所有的处置都是字符串,都是js中的基础例子。当这些 *** 纵停止时,重建的根正在生长。需要将它们更正到这个字符串中,以便记录原来的开始和结束状态,然后插入新的。很复杂,借用很复杂,但是以前总比以前一个一个穿越人物好。在常规捕捉中,有一个婚姻的指标,可以间接使用,借来可以承受。

然而,那只是处理段落内部标签的结果。段落中一定有很多文字借用。我该怎么办?

正规的婚姻只是内在标签的结果,有一些内在标签。哦,对了,有一个婚姻的索引,上一次婚姻的位置减去上一次处分的程度,就是一个间接文的开头。下一次婚姻的索引-1是那个间接文本的结尾。只是在结婚的过程中,到最后还是要处理的。回到无聊的老路。。。

好烦,我毫不怀疑分开一段可以这么繁琐!

突然意识到有文本节这种工具,可以通过删繁就简。规律性的会先到了边上,所有间接处理下跌的板块都不会停下来。

文本部分被单独和间接换行,而标签部分停止内容的换行。那样的话,间接处理就是dom,比较麻烦。

在文本部分放置标签?那是一种固执的笑吗?是的,它是,也不是。文本段确实只能放文字,但是我间接把标签放出来的时候,它会主动转义,所以一开始没必要换出来。

好了,计划完成了,计划的逻辑有多简单,代码逻辑自然不烦。

/**

*评论内容分段处置。

*@param{jqueryobject/HTMLElement/string}$contentannotation要释放的jQ工具或htmlelement或其对应的选取器

*/

函数splitcontent($content){

$content=$($content);

$content.find(splitconfig.unittag)。每个(函数(索引,项目){

var$item=$(item),

text=$。trim($item.text());

如果(!文字)返回;

varnodes=$item[0]。子节点;

$.每个(节点,函数(I,节点){

开关(node.nodeType){

案例三:

//文本节点

//因为是文本段,所以标签被转义,然后就再也回不来了。

node.data='<'+splitconfig.wraptag+'>;'+

node.data.replace(splitconfig.splitreg,'$&<'+splitconfig.wraptag+'>;')+

'';

打破;

案例1:

//元素节点表面

varinnerHtml=node.innerHTML,

start=“”,

end=“”;

//如果有内部借用的间接标签,会先丢失。

varstartresult=/^<;w+?>/.exec(innerHtml);

if(startResult){

start=startResult[0];

innerHtml=innerHtml.substr(start.length);

}

varendresult=/<;/w+?>$/.exec(innerHtml);

if(endResult){

end=endresult[0];

innerHtml=innerHtml.substring(0,endresult.index);

}

//更新内部内容

node.innerHTML=start+

<'+splitconfig.wraptag+'>;'+

innerhtml.replace(splitconfig.splitreg,'$&<'+splitconfig.wraptag+'>;')+

''+

结束;

打破;

默认值:

打破;

}

});

//处理文本部分中的转义html标记

$item[0]。innerHTML=$item[0]。innerHTML

。替换(新的正则表达式('<'+splitconfig.wraptag+'>;','g','<'+splitconfig.wraptag+'>;')

。替换(新的正则表达式(</'+splitconfig.wraptag+'>;'、'g')、'');

$item.find(splitConfig.wrapTag)。addclass(splitconfig.wrapcls);

});

}

上面的代码中,一开始在text部分交换转义包标签似乎比较麻烦,但解决的办法是ES5之前的JavaScript实际上并不支持正则换行符(也就是正则表达式中的“回看”)。是一种前后标签包裹的方式:停止粗换,只有签名才能一起换。

紧急治疗

在书的中间,我们已经完成了文本的获取和切分。上面我们要做的就是鼠标上移时让课文接触背诵,移开时背诵。

移动鼠标,只读一遍,基于书的两面,用mouseenter打mouseleave来完成。

本国:

不冒泡,不背诵女性元素。

没有重复触摸,当一个元素在里面移动时没有重复触摸。

/**

*页面上正在书写以下样式。

*/

函数createStyle(){

if(document.getelementbyid('speak-light-style'))返回;

varstyle=document.createelement('style');

style.id='speak-light-style';

style.innerText='.'+splitconfig.highlightcls+'{'+splitconfig.hightstyle+'}';

document.getelementsbytagname('head')[0]。appendChild(style);

}

//无注释需求列举的标签用逗号分隔。

  varspeakTags='a,p,span,h1,h2,h3,h4,h5,h6,img,input,button';varspeakTags='a,p,span,h1,h2,h3,h4,h5,h6,img,input,button';

$(文档)。on('mouseenter.speak-help',speakTags,function(e){

var$target=$(e.target);

//移除

if($target.parents('.')+splitConfig.wrapCls)。length||$target.find('.')+splitConfig.wrapCls)。长度){

返回;

}

//图片样式将像其他样式一样被处理。

  if(e.target.nodeName.toLowerCase()==='img'){if(e.target.nodename.tolowercase()==='img'){

$target.css({

边框:“2px纯色#000”

});

}否则{

$target.addclass(splitconfig.highlightcls);

}

//开始阅读

speaktext(getText(e.target));

}).on('mouseleave.speak-help',speakTags,function(e){

var$target=$(e.target);

if($target.find('.')+splitConfig.wrapCls)。长度){

返回;

}

//图片样式

  if(e.target.nodeName.toLowerCase()==='img'){if(e.target.nodename.tolowercase()==='img'){

$target.css({

边框:“无”

});

}否则{

$target.removeclass(splitconfig.highlightcls);

}

//截至语音

stopspeak();

});

//段落向下文本背诵

$(文档)。on('mouseenter.speak-help','.'+splitConfig.wrapCls,函数(e){

$(这个)。addclass(splitconfig.highlightcls);

//开始阅读

speaktext(getText(this));

}).on('mouseleave.speak-help','.'+splitConfig.wrapCls,函数(e){

$(这个)。removeclass(splitconfig.highlightcls);

//截至语音

stopspeak();

});

注意把段降的语音处理和其他地方分开。为什么?由于segmentdrop是块级元素,当鼠标移入segmentdrop中的空gap时,比如:空gapsegmentdrop前后,endingindentation,endingsurplus空gap等。,它不应该被触摸和背诵。如果不止损,就停止那些区域接触和背诵整段,掉/

文本分解语音

以前我们间接用两种方法,speakText(文本)和stopSpeak(),来触碰演讲朗诵的结尾。

我们来看看如何实现那两个功能。

其实,当代读者的默许曾经提供了“向上”的功能:

varspeechSU=新窗口。speechsynthesisatterance();

SpeechSU.text='你好,世界!';

window.speechsynthesis.speech(speechsu);

建立到阅读器控制台,看看你是否能听到声音。(需要Chrome33+,Firefox49+或IE-Edge)

您可以 *** 作这两个API:

语音合成用于语音分解。

Lang:词汇决定了语言的表达方式。

Pitch:获取并设置异常情况下的音调。

Rate:speed获取并设置说话的速度。

Text:text获取并设置在说出话语时将被合成的文本。

声音:声音获取并设置用于说话的声音。

音量:音量获取并设置异常时的音量。

Onboundary:单词或句子间隙接触,即单词或句子边界分离时接触。

Onend:当讲话结束时触摸该按钮。

错误:出错时,触摸它,当发生错误阻止异常成功时触发。

onmark:当说出的话语到达一个已命名的SSML“mark”标签时触发。

Onpause:长时间停止,中途异常暂停时触发touchandreceive。

Onresume:从头开始播放时,当暂停的话语恢复时触发touch。

Onstart:开始时,当异常已经开始说话时,触摸点火。

语音合成:用于背诵

顿了顿:只能看很久吗?一个布尔值,如果语音合成对象处于暂停状态,则返回true。

Pending:只读,如果惟一性队列包含尚未开放的话语,您能处理一个返回true的布尔值吗?

口语:只读,你能背诵一个返回true的布尔值吗?如果一个话语正在被口语化,即使语音合成处于暂停状态?

声音改变时触摸

Cancel():情况要背。从话语队列中删除所有话语。

GetVoices():获取阅读器支持的语音包列表返回代表当前设备上所有可用语音的语音合成语音对象列表。

Pause():将语音合成对象长时间置于暂停状态。

Resume():将语音合成对象置于非暂停状态:如果它已经暂停,则恢复它。

Speak():要读取分解后的语音,参数必须是speechsynthesis的真实示例(将一个语音发送到语音队列);当任何其他话语在它被说出之前排队时,它将被说出。

具体api战法澄清可以参考:

MDN-语音合成交互

MDN-语音合成

那么书中的两种方法可以写成这样:

varspeaker=新窗口。speechsynthesisatterance();

varspeakTimer,

停止计时器;

//开始阅读

函数speakText(text){

cleartimeout(speaktimer);

window.speechsynthesis.cancel();

speaktimer=setTimeout(function(){

speaker.text=text

window.speechSynthesis.speak(扬声器);

},200);

}

//截至背诵

函数stopSpeak(){

cleartimeout(stoptimer);

cleartimeout(speaktimer);

stoptimer=setTimeout(function(){

window.speechsynthesis.cancel();

},20);

}

因为语音分解是一个同步 *** 作,所以在这个过程中,上述处理是被停止的。

当代的阅读器曾经内置了这个功能,这两个API的兼容性如下:

特征

边缘

火狐(壁虎)

微软公司出品的web浏览器

歌剧

旅行队

(WebKit)基本

支架33

(是)

49(49)

不支持

如果要兼容其他阅读器,大概需要一个完善的兼容的处理方案。如果能完成要求的服务,按照给定的文字返回响应语音即可。百度语音http://yuyin.baidu.com/docs将提供这种服务。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/768632.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-02
下一篇 2022-05-02

发表评论

登录后才能评论

评论列表(0条)

保存