先来个效果图韵下味:

需求:

  1. 音频的播放,暂停,中间按钮状态的变化,播放时实时更新播放进度;
  2. 前进15s,后退15s;
  3. 进度条拖动。

一开始想着这3个功能应该挺简单的。不就是播放,暂停,前进,后退么~呵~写的时候发现自己还是太年轻。当然,这跟自己的技术功底有关系。现在把我遇到的难点及要注意的点说一下~

  1. 需要设置一个名为seekPosition的全局变量,初始值为0。我们要在播放的时候实时记录播放的位置,存到该变量里,这是方便在前进15s 或 后退15s 时计算时间点。
  2. 前进15s时要判断剩余时间是否>15s,如果<15s,则返回到开始位置;
  3. 后退15s时要判断播放时间是否>15s,如果<15s,则返回到开始位置;
  4. 点击播放时,要先判断seekPisition是否>0,如果>0,则跳转到seekPosition的位置,并播放;
  5. 拖动时,要先让音频停止播放,拖动结束后,再播放音频。并且要计算拖动位置对应的时间。

完整代码:

wxml:

<view class=" audio-content">

  <image src="{{logo640x360}}" class="bg-blur"></image>
<view class="bg-gray"></view>
<view class="container-cover">
<view class="cover">
<image src="{{logo640x360}}" class="cover-image"></image>
<view class="cover-tip">词不达意.mp3</view> </view>
</view>
<view class="audio-inner row item-center">
<view class="audio-desc">{{currentProcess}}</view>
<view class="audio-progress-wrap">
<van-slider value="{{sliderValue}}" step="{{sliderStep}}" active-color="#09bb07" use-button-slot bind:change="onSliderChange" bind:drag="onSliderDrag">
<view class="slider-button" slot="button"></view>
</van-slider>
</view>
<view class="audio-desc">{{productDetail.duration}}</view>
</view> <!-- 播放器控制条 -->
<section class="speech-player js_control_bar">
<view class="player-bar row justify-center item-center">
<view class="backward js_audio_backward" title="后退15s">
<ss-icon name="back-15" size="32px" color="#fff" block="{{true}}" bind:click="backward" />
</view>
<view class="play" title="播放/暂停">
<view class="circle-loading" wx:if="{{loading}}"></view>
<ss-icon name="play-outline" size="50px" color="#fff" block="{{true}}" wx:if="{{pause}}" bind:click="audioPlay" />
<ss-icon name="pause-outline" size="50px" color="#fff" block="{{true}}" wx:if="{{playing}}" bind:click="audioPause" />
</view>
<view class="forward js_audio_forward" title="前进15s">
<ss-icon name="forward-15" size="32px" color="#fff" block="{{true}}" bind:click="forward" />
</view>
</view>
</section>
</view>

这里面用到了有赞的小程序组件 icon组件 和 slider 组件。如果你要用的话把上面的 <ss-icon> 换成<van-icon>,并且需要自己找阿里矢量图标库查找对应的图标。

js:

// components/product/audio/index.js

let audioUrl = "",
seekPosition = 0;
const audioContext = wx.createInnerAudioContext(); Component({
options: {
multipleSlots: true,
addGlobalClass: true
}, /**
* 组件的属性列表
*/
properties: {
productId: Number,
},
/**
* 组件的初始数据
*/
data: {
pause: true,
playing: false,
loading: false,
productDetail: {},
audioDuration: 0,
currentProcess: '00:00',
sliderStep:1
}, /**
* 组件的方法列表
*/
methods: {
//音频播放
audioPlay(e) {
const _this = this;
let audioDuration = _this.data.audioDuration;
if (audioUrl) {
if (seekPosition) {
//如果有指定位置,则跳转到指定位置
audioContext.seek(seekPosition);
}
audioContext.play();
_this.setData({
pause: false,
playing: true,
loading: false,
})
} else {
//getJSON是我自己封装的
ss.getJSON('获取音频如果需要发送请求,这里面放请求地址', {
放你自己的参数
}, res => {
audioUrl = res.t;
audioContext.src = audioUrl;
if (seekPosition) {
audioContext.seek(seekPosition);
}
audioContext.play();
audioContext.onPlay(() => {
console.log('onPlay')
}) audioContext.onWaiting(() => {
console.log('onWaiting')
_this.setData({
pause: false,
playing: false,
loading: true,
})
}) audioContext.onCanplay(() => {
console.log('onCanplay')
_this.setData({
pause: false,
playing: true,
loading: false
})
setTimeout(() => {
audioContext.duration
}, 500) _this.audioStatus();
}) audioContext.onError((res) => {
console.log(res.errMsg)
})
})
} }, //播放暂停
audioPause: function() {
const _this = this;
audioContext.pause();
_this.setData({
pause: true,
playing: false,
loading: false
})
}, //记录播放状态
audioStatus: function() {
const _this = this;
//音频播放进度更新事件
audioContext.onTimeUpdate(() => {
seekPosition = audioContext.currentTime;
_this.setData({
currentProcess: ss.formatSecToMin(audioContext.currentTime),
sliderValue: audioContext.currentTime / _this.data.audioDuration * 100,
})
})
//音频播放结束
audioContext.onEnded(() => {
seekPosition = 0;
_this.setData({
sliderValue: 0,
currentProcess: '00:00',
playing: false,
pause: true
})
})
}, //开始拖动
onSliderDrag(e) {
const _this = this;
if (_this.data.playing) {
_this.audioPause()
}
let sliderValue = e.detail.value;
seekPosition = _this.data.audioDuration / 100 * sliderValue;
_this.setData({
currentProcess: ss.formatSecToMin(seekPosition)
}) }, //拖动结束
onSliderChange(e) {
const _this = this;
_this.audioPlay()
}, //前进15s
forward() {
const _this = this,
audioDuration = _this.data.audioDuration;
let currentTime;
if (_this.data.playing) {
currentTime = audioContext.currentTime;
}
if (_this.data.pause) {
currentTime = seekPosition;
} if (audioDuration - currentTime > 15) {
seekPosition = currentTime + 15;
_this.setData({
sliderValue: seekPosition / audioDuration * 100,
currentProcess: ss.formatSecToMin(seekPosition)
});
} else {
seekPosition = audioDuration;
_this.setData({
sliderValue: 0,
currentProcess: '00:00'
});
}
if (audioUrl && _this.data.playing) {
audioContext.seek(seekPosition);
}
}, //后退15s
backward() {
const _this = this,
audioDuration = _this.data.audioDuration;
let currentTime;
if (_this.data.playing) {
currentTime = audioContext.currentTime;
}
if (_this.data.pause) {
currentTime = seekPosition;
} if (currentTime > 15) {
seekPosition = currentTime - 15;
} else {
seekPosition = 0;
}
_this.setData({
sliderValue: seekPosition / audioDuration * 100,
currentProcess: ss.formatSecToMin(seekPosition)
});
if (audioUrl && _this.data.playing) {
audioContext.seek(seekPosition);
}
}
}
})

大概就是这些了~有更好解决方案的欢迎留言哈~~

微信小程序——音频播放器的更多相关文章

  1. 微信小程序音频播放 InnerAudioContext 的用法

    今天项目上涉及到了微信小程序播放音频功能,所以今天跟着一些教程做了个简单的播放器 1.实现思路 刚开始想着有没有现成的组件可以直接用,找到了微信的媒体组件 audio,奈何看着 1.6.0版本开始,该 ...

  2. 微信小程序音乐播放器

    写在前面 1.入门几天小白的作品,希望为您有帮助,有好的意见或简易烦请赐教 2.微信小程序审核音乐类别已经下架,想要发布选题需慎重.附一个参考链接,感谢https://www.hishop.com.c ...

  3. 微信小程序 - 音频播放(1.2版本和1.2版本之后)

    不多说了,直接贴code // 1.2版本以后便不在维护 wx.getBackgroundAudioManager({ success:function(res){ var status =res.s ...

  4. 微信小程序音乐播放器组件

    wxml <image bindtap="click" src="{{isPlay?'/images/':'/images/'}}"/> JS Pa ...

  5. 微信小程序自运营器 微信小程序自动运营器(让你的微信小程序,公众号零运营成本,24小时全自动运营)

    自动发单,自动评价,自动评论,自动推广 微信小程序自运营器  微信小程序自动运营器(让你的微信小程序,公众号零运营成本,24小时全自动运营) 我们会根据你的微信公众号或微信小程序定制开发带有一定AI智 ...

  6. 微信小程序api拦截器

    微信小程序api拦截器 完美兼容原生小程序项目 完美兼用小程序api的原本调用方式,无痛迁移 小程序api全Promise化 和axios一样的请求方式 小程序api自定义拦截调用参数和返回结果 强大 ...

  7. 微信小程序音频背景播放

    由于微信小程序官方将音频的样式固定死了,往往再工作中和UI设计师设计出来的样式不符,故一般都采用背景音频播放来实现自定义的UI样式的音频播放,即使用官网API提供的BackgroundAudioMan ...

  8. 微信小程序音乐播放

    最近在写一个艾美食艾音乐的微信小程序,其中有用到音乐播放的功能,基本播放切换功能已经实现,但是在反复切换歌曲.重新进入歌曲以及单曲循环.列表循环的测试过程中还是发生了bug,特此写一篇文章,捋一下思路 ...

  9. 微信小程序音频长度获取的问题

    小程序推荐使用wx.createInnerAudioContext()创建的innerAudioContext,我们也通过这个接口创建音频.音频的长度可以通过属性获取: 但是,给innerAudioC ...

随机推荐

  1. 通过Fastdfs进行文件上传服务(文件和图片的统一处理)

    1.文件上传简单流程分析图: 2.Fastdfs介绍: Fastdfs由两个角色组成: Tracker(集群):调度(帮你找到有空闲的Storage) Storage(集群):文件存储(帮你保存文件或 ...

  2. layui 上传图片 实现过程

    layui.user一个页面只能有一个,写多了会实现js效果 上传图片官方文档有很多功能,但是演示的代码只是一个一个功能演示,如果要综合起来js代码不是简单的拼凑,需要放在指定位置,比如下面的限制文件 ...

  3. Go 基本数据类型

    Go基础语法 package main import "fmt" func main(){ fmt.Println("Hello world") } 注意点: ...

  4. android studio下 library打包文件(.aar)和本地引用

    关键点: 利用Gradle发布本地maven库支持android library 打包文件(*.aar) 的本地引用 开发环境: windows7 64位操作系统 android studio0.5. ...

  5. 【题解】Luogu P5341 [TJOI2019]甲苯先生和大中锋的字符串

    原题传送门 实际按照题意模拟就行 我们先求出字符串的sa 因为要在字符串中出现k次,所以我们枚举\(l,r(r-l+1=k)\)看一共有多少种合法的方案 合法方案的长度下界\(lb\)为\(Max(h ...

  6. 线程池及Executor框架

    1.为什么要使用线程池? ​ 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过 ...

  7. 在 Target 中获取项目引用的所有依赖(dll/NuGet/Project)的路径

    原文:在 Target 中获取项目引用的所有依赖(dll/NuGet/Project)的路径 在项目编译成 dll 之前,如何分析项目的所有依赖呢?可以在在项目的 Target 中去收集项目的依赖. ...

  8. asp.net core 核心对象解析

    首先声明这篇文章的所有内容均来自https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html ----感谢大内老A(artec ...

  9. 2019 华云数据java面试笔试题 (含面试题解析)

    本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.华云数据等公司offer,岗位是Java后端开发,最终选择去了华云数据. 面试了很多家公司,感觉大部分公司考察的点 ...

  10. Excel表格快速将公式运用到一整列

    假设你的公式在B2单元格,需要复制公式到B3:B999,那么你先选择包含公式单元格的所有需要复制公式的单元格(B2:B999),然后按Ctrl+D即可全部填充.