需求与bug解决

做 H5开发的一个需求:页面内有一个按钮点击可以播放语音,产品提供的素材是多段语音,并配有对应文字;

bug1: 切换到后台时,语音还在播放,

解决方法:增加 visibilitychange 监听事件,用 document.hidden 判断是否处于后台。

  mounted() {this.audioTemp = new Audio(AthenaData.audioList[0].voice);// 切到后台停止语音document.addEventListener('visibilitychange', () => {if (document.hidden) {this.musicDisabled = false; // 按钮状态this.audioTemp.pause();}});},

bug2: API can only be initiated by a user gesture

原因:部分安卓机要求调用 audio.play() 这个接口必须要用户手势触发,也就是必须是真实的用户操场类似 click之类的事件去触发才行,用js主动去触发dom的click的话也是无效的!

解决方案有二:1. 安卓端上有对应的 api 设置可以取消这个限制,但一定会有合规方面的风险(法务检测那边可能无法通过)2.将多段语音合成一段。

功能实现

template:

        // 播放按钮       <divv-image.normal="musicDisabled ? AthenaData.horn1 : AthenaData.horn2"class="horn1"@click="onBgmMusicClick"/>// 滚动文字<divref="box"class="tips-box"><divref="content"class="tips-content":style="tranlateDo?{transition: `all ${tranlateTime}s linear`,transform: `translateX(-${tranlatex}px)`,}:{transform: 'translateX(0)'}">{{ AthenaData.audioList[voiceIndex].label }}</div></div>

data:

  data() {return {AthenaData,  // 数据musicDisabled: false,  // 播放按钮状态audioTemp: null,  // 语音对象voiceIndex: 0,  // 文字索引tranlateDo: false,  // 文字滚动状态tranlatex: 0,     // 文字滚动距离timeoutTicket: null,  // 当前文字voiceTimeoutTicket: null,  // 下一段文字};},

mounted:

mounted() {// 设置语音播放列表this.audioTemp = new Audio(AthenaData.audioList[0].voice);this.audioTemp.onended = () => {this.musicDisabled = false;this.audioTemp.pause();this.audioTemp.load();this.tranlateDo = false;this.voiceIndex = 0;clearTimeout(this.voiceTimeoutTicket);};// 切到后台停止语音document.addEventListener('visibilitychange', () => {if (document.hidden) {this.musicDisabled = false;this.audioTemp.pause();this.tranlateDo = false;this.voiceIndex = 0;this.audioTemp.load();if (this.timeoutTicket) {clearTimeout(this.timeoutTicket);}clearTimeout(this.voiceTimeoutTicket);}});},
  computed: {// 读当前文字滚动的时间tranlateTime() {// 三目运算符容错return AthenaData.audioList[this.voiceIndex]? AthenaData.audioList[this.voiceIndex].time - 1// 每段语音的首末有半秒背景音乐: 1;},},

methods:

  methods: {// 播放语音按钮回调onBgmMusicClick() {this.musicDisabled = !this.musicDisabled;if (this.musicDisabled && AthenaData.audioList.length) {this.audioTemp.play();this.setLabelPlay();}if (!this.musicDisabled) {this.audioTemp.pause();this.tranlateDo = false;this.voiceIndex = 0;this.audioTemp.load();if (this.timeoutTicket) {clearTimeout(this.timeoutTicket);}clearTimeout(this.voiceTimeoutTicket);}},//设置文字动画setLabelPlay() {// 语音有半秒前奏播放完后 再开始文字动画this.timeoutTicket = setTimeout(() => {this.tranlateDo = true;this.tranlatex = this.$refs.content.offsetWidth - this.$refs.box.offsetWidth;}, 500);clearTimeout(this.voiceTimeoutTicket);this.voiceTimeoutTicket = setTimeout(() => {
// 目前只有三段文字,若索引为2说明到最后一段,置0停掉动画;否则处理下一段(+1后则显示下一段文字)this.voiceIndex = this.voiceIndex === 2 ? 0 : this.voiceIndex + 1;
// 以下为控制下一段文字动画的逻辑if (this.voiceIndex !== 0) {
// 停掉动画 从头滚动this.tranlateDo = false;this.tranlatex = 0;
// 开始滚动this.setLabelPlay();} else {clearTimeout(this.voiceTimeoutTicket);}}, parseInt(AthenaData.audioList[this.voiceIndex].time, 10) * 1000); // 这个时间为当前动画持续的时间},}

最终效果如下,资源链接

屏幕录制2022-07-28 18.51.06

其实,不难发现,语音和文字的单独控制,只不过是卡住时间让效果看起来是同步。除此之外,还可以扩充暂停功能:播放语音中途点击按钮让语音和文字滚动暂停,再次点击时接着上述效果。原生实现方法只需增加一个变量记录点击时文字已滚动的距离,然后再次点击时进行判断,让动画接着滚动;如果引入其他动画库也许会有直接的API控制动画的暂停,实现起来更加简单。

Audio介绍

什么?你不知道audio是什么?它是h5新特性之一,audio可以理解为普通的dom对象,相关属性方法事件如下:

Audio对象的属性

Audio对象的方法

Audio对象的事件

事件和方法很像,只不过是可以传入回调函数增加更多逻辑

安卓机调用 audio.play()时 报错:API can only be initiated by a user gesture相关推荐

  1. 在visual studio 2010+中调用ffmpeg编译时 报错error LNK xxxx: 模块对于 SAFESEH 映像是不安全的。...

    解决该错误的方法: 1.右键单击该项目选择"属性". 2.在属性页中选择:配置选项->链接器->命令行. 3. 在命令行的"其他选项"中输入/SAF ...

  2. c# 传递Null的string值导致的调用C++的dll报错 Attempted to read or write protected memory.

    c# 调用C++的dll报错 Attempted to read or write protected memory: 原因是:c# 传递Null的string值导致的,将Null改为string.e ...

  3. Windos环境下kafka配置启动Zookeeper时,报错:Invalid config, exiting abnormally.

    Windos环境下kafka配置启动ZooKeeper时,报错:Invalid config, exiting abnormally. 执行命令: D:\kafkaOnWindows\kafka_2. ...

  4. C# 调用NationalInstruments的dll报错问题 未能加载文件或程序集

    C# 调用NationalInstruments的dll报错问题 问题原因:dll版本不匹配导致的,需要做如下操作解决问题 未能加载文件或程序集"NationalInstruments.Co ...

  5. 调用webservice接口,报错:(十六进制值0x01)是无效的字符。

    文章目录 #事故现场 #分析 #解决方法 #事故现场 调用webservice接口,报错:(十六进制值0x01)是无效的字符. 如图: 意思是webservice返回的信息中包含无效的字符,无法解析成 ...

  6. jni调用 kotlin 方法是报错 kotlin An operation is not implemented: Not yet implemented

    项目场景: 提示:这里简述项目相关背景: jni 调用 kotlin中方法会报错 问题描述 TODO("Not yet implemented") 没有去掉代码: override ...

  7. linux执行.sh文件时,报错:XXX.sh: Permission denied(没有权限)

    linux执行.sh文件时,报错:XXX.sh: Permission denied(没有权限) 解决方法:修改对该文件的权限 例如报错: bash: ./zkServer.sh: Permissio ...

  8. gpt磁盘标签linux,解决安装CentOS6.5时 报错 提示“sda 必须有一个GPT磁盘标签”

    解决安装CentOS6.5时 报错 提示"sda 必须有一个GPT磁盘标签" 今天想在thinkpad t430u上安装CentOS6.5 时总共遇到了两个问题 1> u盘安 ...

  9. RF踩坑之调用pyautogui鼠标操作报错

    因为要用到拖拽页面元素,但是robotframework 自带的drag and drop方法无法运行但不报错. 百度说是selenium 的darg and drop 不支持html5. 只能自己调 ...

  10. 调用微信的接口报错errcode: 40164 invalid ip

    调用微信的接口报错errcode: 40164 调用微信的接口报错 { errcode: 40164, errmsg: 'invalid ip 117.100.47.169 ipv6 ::ffff:1 ...

最新文章

  1. Java基础看这一篇就够了
  2. element input 只能输入数字_Python之input()函数
  3. cocos 报错dts文件未导入_cocos2dx 3.4项目 导入到 eclipse 爬过的坑
  4. BugkuCTF-MISC题隐写3
  5. java队列实现限流,java中应对高并发的两种策略
  6. python函数降低编程复杂度_Python-面向对象编程
  7. android每秒 1,在Android 5.1中调度每秒的警报
  8. 输入框设置等宽字体_Glyphs 官方教程 | 字体命名
  9. 用python简单代码做一个计算器
  10. elipse下载安装教程
  11. 小米路由器R1C或R1CM小米R1C 原厂Bootloader和epproom
  12. 阅读HashMap(1.6)源码所做的一些记录
  13. c++ 11 原子操作库 (std::atomic)(三)
  14. TPLINK免驱版网卡插上后无法识别到CD驱动器怎么办?
  15. Bacteria(优先队列)
  16. 前端的Vue相关的项目经验
  17. 干货 | 科研必备的软件神器
  18. 项目管理(PMP)真题解析(二)
  19. 轻松省力清洁地面,分分钟搞定家务,云米智能洗地机Cyber Lite体验
  20. 【python】什么是python?python有什么用?

热门文章

  1. 关于计算机的发展史手抄报图片,历史手抄报精选图片内容
  2. C++中带.h与不带.h的头文件
  3. Lounge Lizard EP-4 for Mac(电钢琴插件)v4.2.5破解版
  4. 用javascript 判断IE窗口是否打开
  5. Kafka原理介绍+安装+基本操作
  6. 炒币玩波段为什么一定要设置止损止盈?
  7. 奋斗在美国湾区,码农的生活
  8. 华为发放20亿元奖金,抗击美国断供,奖励员工加班奋斗,网友:他们应得的...
  9. OpenStack之Live-migration
  10. 十大流行开源软件推荐