实现读书软件的听书功能,适配app,小程序,h5

实现效果展示功能带你包括: 章节,倒计时,上一章,下一章,播放,暂停,倍速:
uniapp官方uni.createInnerAudioContext()的文档地址:官网文档参考地址
首先分步骤介绍功能:

  1. 章节(这个调取接口遍历数据就可以,弹出层的形式展示)
  2. 倒计时
  3. 上一章
  4. 下一章
  5. 播放
  6. 暂停
  7. 倍速

我这里页面嵌入一个audio的组件 ,组件名称audio

components: {Audio},
data() {return {sourceList:[], //章节的数据bookImg: '', //图书的封面图bookName:'',//书名chapterName: '', //章节名称chapterUrl:'',//播放的章节地址id: null, //书的iditemId:'', //章节id}
},
<template><view class="content"><view class="" v-if="sourceList.length > 0"><Audio @handleId='handleId'  :sourceList='sourceList' :bookResourceId='bookResourceId' :bookName='bookName' :bookImg='bookImg' :id='id' :wxId='id' :chapterName='chapterName' :chapterUrl='chapterUrl'></Audio></view></view>
</template>
handleId(id){this.id = id
},

Audio的页面代码:

<template><view class="audio_content"><view class="audio_box"><image class="audio-img" :src="bookImg" mode="aspectFill"></image><view class="img-pop"></view><view class="audio-info"><!-- #ifdef APP-PLUS --><view class="header-box"><u-icon name="arrow-left" style="margin-left: 32rpx;" color="#ffffff" size="24"@click="goBack()"></u-icon><u-icon style="margin-right: 44rpx;" name="share-square" color="#ffffff" size="24"@click="appShare"></u-icon></view><!-- #endif --><view class="course_name">{{bookName}}</view><view class="audio_title">{{bgAudioMannager.title}}<!-- {{bookTitle}} --></view><view class="book-box"><image class="book-img" :src="bookImg" mode="aspectFill"></image></view><view class="audio_process"><view class='slider'><!-- <slider :value="currentTime" step="1" min="0" :max="duration"block-color="#fff" activeColor="#DC3232" inactiveColor="#8B8D7F" block-size="12"@change="seek=true,clickSeek($event.detail.value)" @changing="seek=true,current=$event.detail.value" /> --><slider class="audio-slider" activeColor="#DC3232" block-size="12" :value="currentTime":max="duration" @changing="seek=true,current=$event.detail.value"@change="seek=true,clickSeek($event.detail.value)"></slider></view><view class="time_cons"><view class="duration">{{ time.getAudioTime(currentTime) }}</view><view class="end">{{ time.getAudioTime(duration) }}</view></view></view><view class="utils"><view @tap="showModal"><image class="change-list" :src="$staticUrl + 'static/index/audio-list.png'" mode=""></image></view><view class="timeBox" @click="openTime"><image class="change-time" :src="$staticUrl + 'static/index/audio-time.png'" mode=""></image><view class="timeText">{{timeMsg}}</view></view><!-- 上一章 --><view class=""><image v-if="!lastPlay" @click="lastMusic" class="change":src="$staticUrl + 'static/audio.png'" /><image @click="lastMusic" class="change" v-if="lastPlay":src="$staticUrl + 'static/index/audio-pre.png'" /></view><!-- 播放 --><view class=""><image @click="playOrpause" v-if="!playStatus" class="change-start":src="$staticUrl + 'static/index/audio-start.png'" /><image @tap="playOrpause" v-if="playStatus" class="change-start":src="$staticUrl + 'static/index/jgq_sxzt.png'" /></view><!-- 下一章 --><view class="prev next"><image @click="nextMusic" v-if="nextPlay" class="change":src="$staticUrl + 'static/index/audio-next.png'" /><image v-if="!nextPlay" class="change" :src="$staticUrl + 'static/audio-g.png'" /></view><view class="beisu" @click="showPlaybackRate = true"><text class="num">{{rateText}}</text><!-- <text class="text">倍速播放</text> --></view></view></view></view><u-popup :show="hideModal" @close="close" @open="open" :round="10"><!-- <view class="empty-box" id="empty-box"></view> --><scroll-view scroll-y style="height: 100%;"><view class="content" :style="'transform:translateY(' + translateY + 'px);'" :animation="animate"><view class="header"><view class="title">目录</view><view class="right" @click="close"><u-icon name="close" color="#000000" size="20"></u-icon></view></view><view><PeriodList :bookCoverImg='bookImg' :bookName='bookName' :supCode='supCode':sourceType='sourceType' :id='id' type='audio' :chapterList='sourceList'@startAudio='startAudio' :bookResourceId='bookResourceId'></PeriodList></view></view></scroll-view></u-popup><!-- 倍速弹出层 --><u-popup :show="showPlaybackRate" @close="closePlaybackRate" @open="openPlaybackRate" :round="10"><!-- <view class="empty-box" id="empty-box"></view> --><scroll-view scroll-y style="height: 100%;"><view class="content" :style="'transform:translateY(' + translateY + 'px);'" :animation="animate"><view class="header"><view class="title">倍速选择</view><view class="right" @click="closePlaybackRate"><u-icon name="close" color="#000000" size="20"></u-icon></view></view><view class="rate-listBox"><view class="rate-list" @click="handleRate(0.5)">0.5倍速</view><view class="rate-list" @click="handleRate(1)">1.0倍速</view><view class="rate-list" @click="handleRate(1.5)">1.5倍速</view><view class="rate-list" @click="handleRate(2.0)">2.0倍速</view></view></view></scroll-view></u-popup><u-popup :show="showCloseTime" @close="closeTime" @open="openTime" :round="10"><!-- <view class="empty-box" id="empty-box"></view> --><scroll-view scroll-y style="height: 100%;"><view class="content" :style="'transform:translateY(' + translateY + 'px);'" :animation="animate"><view class="header"><view class="title">设置倒计时关闭</view><view class="right" @click="closeTime"><u-icon name="close" color="#000000" size="20"></u-icon></view></view><view class="rate-listBox"><!-- <view class="rate-list" @click="handleCloseTime(11)">1分钟</view><view class="rate-list" @click="handleCloseTime(12)">5分钟</view> --><view class="rate-list" @click="handleCloseTime(15)">15分钟</view><view class="rate-list" @click="handleCloseTime(30)">30分钟</view><view class="rate-list" @click="handleCloseTime(45)">45分钟</view><view class="rate-list" @click="handleCloseTime(1)">1小时</view><view class="rate-list" @click="handleCloseTime(2)">2小时</view></view></view></scroll-view></u-popup><!-- #ifdef APP-PLUS --><sharePop :shows="shows" :href="href" :title='title' @closes='closes'></sharePop><!-- #endif --></view>
</template>

首先进入页面初始化方法:

mounted() {let that = thisthat.initData()},
initData() {let that = this// 页面加载设置当前播放章节的播放信息this.bgAudioMannager = uni.createInnerAudioContext(); //只创建一次之后都是通过this.bgAudioMannager获取this.bgAudioMannager.coverImgUrl = this.bookImgthis.bgAudioMannager.title = this.chapterNamethis.bgAudioMannager.src = this.chapterUrl// this.bgAudioMannager.playbackRate = 1.0 默认倍速为1.0this.newId = this.idthis.duration = this.bgAudioMannager.durationthis.currentTime = this.bgAudioMannager.currentTimethis.currentId = this.idthis.startTime = this.getDate()this.bgAudioMannager.onPlay(() => {console.log('开始播放');});this.bgAudioMannager.onStop(() => {console.log('停止播放');});this.bgAudioMannager.onPause(() => {console.log('暂停播放');});this.bgAudioMannager.onEnded(() => {//初始化 需要的参数console.log('自然播放结束事件');// this.nextMusic()});this.bgAudioMannager.onError((res) => {console.log(res.errMsg);console.log(res.errCode);});// 重要 缺失 音频进入可以播放状态this.bgAudioMannager.onCanplay(() => {this.currentTime = this.bgAudioMannager.currentTimethis.duration = this.bgAudioMannager.durationconsole.log("可播放状态")if (this.bgAudioMannager.duration) {this.duration = this.bgAudioMannager.durationconsole.log(this.bgAudioMannager.duration)}})this.bgAudioMannager.play()//音频进度更新事件this.bgAudioMannager.onTimeUpdate(() => {// console.log("开始监听")/* 判断是否点击过进度条,若点击过,则不要对当前进度条时间current赋currentTime的值因为音频进度更新事件运行频率过快,两个时间会引起冲突,因此需要通过设置开关,判断seek真假,若seek为假则未点击进度条,若seek为真则跳过此次赋值并修改seek值重置为假*/if (!this.seek) {this.currentTime = this.bgAudioMannager.currentTime} else {console.log("修改一次进度条")// this.audio.seek(this.current_tmp)// this.current = this.current_tmpconsole.log(this.currentTime)this.seek = false}if (this.bgAudioMannager.duration) {this.duration = this.bgAudioMannager.duration}})this.bgAudioMannager.onEnded(() => {console.log('播放结束')this.nextMusic()});
},

如果需要页面返回的时候暂停音频:

onUnload() {// clearInterval(timeSet); //停止调用this.bgAudioMannager.pause()this.newTime = 0;this.playStatus = false //暂停播放的状态this.bgAudioMannager.src = '' //当设置了新的 src 时,会自动开始播放
},
destroyed() {this.bgAudioMannager.pause()this.endTime = this.getDate()
},

点击进度条跳转到指定位置:

// 点击进度条
clickSeek(val) {this.currentTime = valthis.bgAudioMannager.seek(val)
},

播放功能

playOrpause() {//根据播放状态进行播放还是暂停if (this.playStatus) {this.bgAudioMannager.pause()this.playStatus = false} else {this.bgAudioMannager.play()this.playStatus = true}
},

上一章和下一章,我们的章节目录结构是两层,逻辑是根据点击的进来的章节id去章节数组中找对应的章节,然后取他的上一节点或者下一节点,注意点:要把拿到的id替换掉当前的id

//上一首
lastMusic() {let that = thisvar currentIndex = nullvar lastIndex = nullvar currentIdx = nullthis.bgAudioMannager.pause()currentIndex = this.sourceList.findIndex((profile) => profile.id == that.id)if (currentIndex == null || currentIndex == -1) {this.sourceList.forEach((item, index) => {//看当前id是否在子章节当中currentIdx = item.twoLevelChapter.findIndex((item1) => item1.id == this.id)lastIndex = item.twoLevelChapter.length - 1//如果在父章节中找到,直接拿当前章节上一章节,通过下标-1的信息if (currentIdx != -1) {if (currentIdx != 0) {this.bgAudioMannager.title = item.twoLevelChapter[currentIdx - 1].chapterNamethis.bgAudioMannager.coverImgUrl = item.twoLevelChapter[currentIdx - 1].chapterUrlthis.bgAudioMannager.src = item.twoLevelChapter[currentIdx - 1].chapterUrlthat.newId = item.twoLevelChapter[currentIdx - 1].idthat.$emit('handleId', this.newId)this.nextPlay = truethis.playStatus = truethis.bgAudioMannager.play()} else {//如果刚好拿到的是第一章节就直接给提示if (index == 0) {this.bgAudioMannager.title = item.twoLevelChapter[0].chapterNamethis.bgAudioMannager.coverImgUrl = item.twoLevelChapter[0].chapterUrlthis.bgAudioMannager.src = item.twoLevelChapter[0].chapterUrlthat.newId = item.twoLevelChapter[0].iduni.showToast({title: '没有上一章节了',icon: 'none'})return} else {this.bgAudioMannager.title = that.sourceList[index - 1].chapterNamethis.bgAudioMannager.coverImgUrl = that.sourceList[index - 1].coverImgUrlthis.bgAudioMannager.src = that.sourceList[index - 1].chapterUrlthat.newId = that.sourceList[index - 1].idthat.$emit('handleId', this.newId)}}}})} else {lastIndex = this.sourceList.length - 1if (currentIndex != 0) {this.bgAudioMannager.title = that.sourceList[currentIndex - 1].chapterNamethis.bookTitle = this.bgAudioMannager.titleconsole.log('title', this.bgAudioMannager.title)this.bgAudioMannager.coverImgUrl = this.sourceList[currentIndex - 1].coverImgUrlthis.bgAudioMannager.src = this.sourceList[currentIndex - 1].chapterUrlthis.newId = this.sourceList[currentIndex - 1].idthat.$emit('handleId', this.newId)this.nextPlay = truethis.playStatus = truethis.bgAudioMannager.play()} else {this.bgAudioMannager.title = that.sourceList[0].chapterNamethis.bgAudioMannager.src = this.sourceList[0].chapterUrlthis.newId = this.sourceList[0].idthis.bgAudioMannager.play()uni.showToast({title: '已经是第一章了',icon: 'none'})return}}this.id = this.newId
},
// 下一首
nextMusic() {let that = thisvar currentIndex = nullvar lastIndex = nullvar currentIdx = nullthis.bgAudioMannager.pause()currentIndex = this.sourceList.findIndex((profile) => profile.id == this.id)if (currentIndex == null || currentIndex == -1) {this.sourceList.forEach(item => {currentIdx = item.twoLevelChapter.findIndex((item1) => item1.id == this.id)lastIndex = item.twoLevelChapter.length - 1if (currentIdx != -1) {if (currentIdx != lastIndex) {this.bgAudioMannager.title = item.twoLevelChapter[currentIdx + 1].chapterNamethis.bgAudioMannager.coverImgUrl = item.twoLevelChapter[currentIdx + 1].chapterUrlthis.bgAudioMannager.src = item.twoLevelChapter[currentIdx + 1].chapterUrlthis.id = item.twoLevelChapter[currentIdx + 1].idthis.nextPlay = truethis.playStatus = truethis.bgAudioMannager.play()} else {this.bgAudioMannager.title = that.sourceList[currentIndex + 1].chapterNamethis.bgAudioMannager.coverImgUrl = that.sourceList[currentIndex + 1].chapterUrlthis.bgAudioMannager.src = that.sourceList[currentIndex + 1].chapterUrlthat.id = that.sourceList[currentIndex + 1].idthis.bgAudioMannager.play()}}})} else {lastIndex = this.sourceList.length - 1if (currentIndex != lastIndex) {this.bgAudioMannager.title = this.sourceList[currentIndex + 1].chapterNamethis.bgAudioMannager.coverImgUrl = this.sourceList[currentIndex + 1].chapterUrlthis.bgAudioMannager.src = this.sourceList[currentIndex + 1].chapterUrlthis.id = this.sourceList[currentIndex + 1].idthis.nextPlay = truethis.playStatus = truethis.bgAudioMannager.play()} else {this.bgAudioMannager.title = this.sourceList[lastIndex].chapterNamethis.bgAudioMannager.coverImgUrl = this.sourceList[lastIndex].chapterUrlthis.bgAudioMannager.src = this.sourceList[lastIndex].chapterUrlthis.id = this.sourceList[lastIndex].idthis.bgAudioMannager.play()uni.showToast({title: '已经是最后一章了',icon: 'none'})return}}//如果播放自动播放完就自动切换下一章this.bgAudioMannager.onEnded(() => {//初始化 需要的参数console.log('自然播放结束eee事件');this.nextMusic()});
},

uniapp使用uni.createInnerAudioContext()实现在app 小程序 h5有声书的播放相关推荐

  1. uniapp使用uni.createInnerAudioContext()实现在app 小程序 h5有声书的倍速功能

    uni.createInnerAudioContext()实现在app 小程序 h5有声书的倍速功能 官网提供的api进行的开发,自我感觉没啥问题,但是在不同的端上好像有的好使有的不好使,暂时不知道啥 ...

  2. uniapp中的分享功能实现(APP,小程序,公众号)

    uniapp中的分享功能实现(APP,小程序,公众号) 1.APP端的分享 app端的分享可以直接使用uniapp封装的方法uni.share,uni-app的App引擎已经封装了微信.QQ.微博的分 ...

  3. WoShop多商户直播电商系统APP+小程序+H5全开源无加密商城源码

    WoShop多商户直播电商系统APP+小程序+H5全开源无加密商城源码 随着多商户直播电商系统的市场走向兴盛,不止直播电商系统的使用越来越广泛,寻求多商户直播电商系统源码的人也越来越多.但源码市场混乱 ...

  4. uni-app 实现 fullpage 组件(适用于微信小程序,h5等)

    uni-app 实现 fullpage 组件(适用于微信小程序,h5等) 业务需求. 本文github 源码地址 1.组件 src/components/FullPage/index.vue < ...

  5. 省钱兄游戏陪玩小程序APP源码uniapp前端源码适配支持(APP+小程序+H5)

    开源代码是用户端uniapp静态部分源码,提供学习使用 使用hbuilder导入即可运行,目前适配小程序,安卓,IOS,H5 游戏类型,我的信息,我的要求,立即找大神 编辑,我想玩的游戏,我想找,其他 ...

  6. uni-app实现上传图片并显示【跨平台开发教程uniapp教程(米饭科技-app小程序h5源码)】

    目录: uni-app上传图片并显示 实现代码 源码获取方法: 会员学习群: uni-app上传图片并显示 实现代码 你可以使用uniapp内置的上传图片组件,然后使用img标签来显示上传后的图片. ...

  7. 校园圈子系统-游戏陪玩系统+派单+社交+多人聊天室-源码部署-APP小程序H5

    陪玩+语音房系统的发展前景 近年来,陪玩+语音房系统成为了广大游戏玩家的热门话题这种系统通过提供线上游戏陪玩的服务使得玩家可以在虚拟世界中找到真正的伙伴,进行愉快的游戏体验. 与此同时,陪玩+语音房系 ...

  8. 陪玩APP小程序H5,一站式搭建,后台须知1

  9. 省钱兄校园跑腿源码(公众号+APP+小程序+Android+IOS)校园跑腿社区跑腿同城跑腿任务兼职小程序uniapp前端模版

    开源代码是用户端uniapp部分源码,使用hbuilder导入即可运行 只提供参考学习使用!已经获得软著!不可商业使用!感谢支持 h5体验地址 h5:https://paotui.xianmxkj.c ...

最新文章

  1. 如何避开项目管理陷阱?
  2. python编程基础之三十三
  3. iview在vue-cli3如何按需加载
  4. 1003. 二哥养细菌—java
  5. Spring Boot程序无法加载主类解决方法
  6. 将Pandas中的DataFrame类型转换成Numpy中array类型的三种方法(亲测)
  7. Asp.Net Core Web应用程序—探索
  8. 广西工学院2000级计算机系,广西工学院管理系信管教研室李明 - 欢迎访问广西科技大学.ppt...
  9. 服务器文件权限在哪里,服务器中的文件权限设置在哪里
  10. SSh三大框架工作原理介绍
  11. SQLite 表达式索引的概念和作用
  12. framework初始化错误,面试大厂应该注意哪些问题?隔壁都馋哭了
  13. 激光投影电视和液晶电视哪个好 激光投影电视和液晶电视什么区别
  14. SQL Server安全(4/11):许可(Permissions)
  15. Arm A-profile feature names
  16. shell、shell命令、shell脚本
  17. kong mysql_Kong网关的安装配置
  18. Array王锐大神力作:osg与PhysX结合系列内容——第4节 角色运动控制
  19. Selenium控制已打开的Chrome浏览器
  20. 瑞熙贝通|数字化实验室综合管理系统V3.0

热门文章

  1. 搭建Eclipse PHP开发环境
  2. 《GAMES104-现代游戏引擎:从入门到实践》-01 学习笔记
  3. Toolbar 工具栏(导航栏)
  4. 腾创秒会达Webrtc视频语音系统,支持BS,CS架构操作灵活简单,免费测试满意再谈购买
  5. ftp是否是分布式文件服务器,分布式文件和FTP服务器
  6. 学生用计算机能算方差吗,用科学计算器计算方差和标准差
  7. 字节Java全能手册火了!多线程/性能调优/设计模式/Spring全家桶/啥都有!
  8. (OpenCV+Python)--RGB转HSI
  9. Operating Systems:Three-Easy-Pieces
  10. 善用 cloneNode 存储 DOM 对象