小程序自定义音频组件,带滚动条

摘要:首先自定义音频组件,是因为产品有这样的需求,需要如下样式的

而微信小程序API给我们提供的就是这样的

而且产品需要小程序有后台播放功能,所以我们不考虑小程序的 audio 组件,即使官方推荐更强大的  wx.createInnerAudioContext 但是不符合需求,所以这里用到的是 backgroundAudioManager()

https://developers.weixin.qq.com/miniprogram/dev/api/getBackgroundAudioManager.html

分析一下:这个页面构成,主要就是进度条和一些icon,进度条之前我自定义了一版,但是效果不理想,最后重构了页面,所以这里用的就是 slider 滑动选择器 https://developers.weixin.qq.com/miniprogram/dev/component/slider.html

  • audio.wxml
<view class="audio">
<image class="bg" src="{{audio_article.lessonImg}}"></image>
<image mode="aspectFill" class="poster" src="{{audio_article.lessonImg}}"></image>
<view class="control-process">
<text class="current-process">{{current_process}}</text>
<slider class="slider"
bindchange="hanle_slider_change"
bindtouchstart="handle_slider_move_start"
bindtouchend="handle_slider_move_end"
min="0"
block-size="16"
max="{{slider_max}}"
activeColor="#fff"
backgroundColor="rgba(255,255,255,.3)"
value="{{slider_value}}"
/>
<text class="total-process">{{total_process}}</text>
</view>
<view class="icon-list ">
<image bindtap="prev" mode="widthFix" src="{{is_first_page?'/images/audio_prev_no.png':'/images/audio_prev.png'}}" class="audio-icon"></image>
<image mode="widthFix" src="{{is_play? '/images/audio_play.png': '/images/audio_paused.png'}}" class="audio-icon audio-play" bindtap="audio_play"></image>
<image bindtap="next" mode="widthFix" src="{{is_last_page?'/images/audio_next_no.png':'/images/audio_next.png'}}" class="audio-icon"></image>
<image hidden mode="widthFix" class="pattern" src="{{is_loop ? '/images/audio_loop.png': '/images/audio_un_loop.png'}}" bindtap="play_loop"></image>
</view>
</view>
滑动事件 bindchange="hanle_slider_change"
开始滑动 bindtouchstart="handle_slider_move_start"
停止滑动 bindtouchend="handle_slider_move_end"
  • audio.wxss

.audio {
position: relative;
width: 750rpx;
height: 640rpx;
padding: 60rpx 32rpx 52rpx;
box-sizing: border-box;
text-align: center;
overflow: hidden;
background: rgba(0,0,0,.18);
} .audio .bg {
position: absolute;
top: 0;
left: -100%;
bottom: 0;
right: 0;
margin: auto;
width: 300%;
height: 300%;
z-index: -1;
filter: blur(40rpx); }
.editor {
padding: 32rpx;
box-sizing: border-box;
color: #333;
font-size: 28rpx;
background: #fff;
}
.editor view {
max-width: 100% !important;
} .audio .poster {
width: 238rpx;
height: 336rpx;
}
/* 音频滚动条start */
.control-process {
margin-top: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.control-process .slider {
width: 526rpx;
}
.control-process text {
font-size: 24rpx;
color: #fff;
}
/* 音频滚动条end */
.audio .icon-list {
position: relative;
margin: 0 auto;
line-height: 102rpx;
} .audio .icon-list .audio-icon + .audio-icon {
margin-left: 72rpx;
} .audio .icon-list .pattern {
position: absolute;
right: 20rpx;
} .audio image {
width: 64rpx;
height: 64rpx;
vertical-align: middle;
} .audio .audio-play {
width: 92rpx;
height: 92rpx;
} .audio .pattern {
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
width: 44rpx;
height: 44rpx;
} /* 音频end */
  • audio.js
/**
* @author: 清风白水 https://www.cnblogs.com/luxiaoyao/
* @date: 2018/07/20 14:36:00
* @program: 重构音频页面
*/
const APP = getApp()
const AUDIOMANAGER = getApp().globalData.global_bac_audio_manager.manage
const AUDIO = getApp().globalData.global_bac_audio_manager
Page({
onLoad: function (e) {
let that = this,
request_param = {
articleId: e.articleId
} this.setData({
article_id: e.articleId
}) wx.request({
url: 'your url',
method: 'POST',
data: {},
header: {
'Content-Type': 'application/json;text/html;charset=utf-8;'
},
success: (res) => {
if (res.data.code == 'A00000') {
AUDIOMANAGER.onPlay(() => {
setTimeout(() => {
that.setData({
is_loading: true
})
}, 300)
}) let response = res.data.data.information // 如果不是从悬浮按钮播放,就重新赋值
if (e.articleId == AUDIO.id && AUDIO.is_play) {
wx.seekBackgroundAudio({
position: Math.floor(AUDIO.time)
})
} else {
audio_background_play(response)
} // 置灰上一首下一首
if (response.preArticleId == 0) {
that.setData({
is_first_page: true
})
}
if (response.nextArticleId == 0) {
that.setData({
is_last_page: true
})
}
}
}
}) //背景音频播放进度更新事件
AUDIOMANAGER.onTimeUpdate(() => {
if (!that.data.is_moving_slider) {
that.setData({
current_process: format(AUDIOMANAGER.currentTime),
slider_value: Math.floor(AUDIOMANAGER.currentTime),
total_process: format(AUDIOMANAGER.duration),
slider_max: Math.floor(AUDIOMANAGER.duration)
})
}
AUDIO.time = AUDIOMANAGER.currentTime
}) // 背景音频播放完毕
AUDIOMANAGER.onEnded(() => {
if (!that.data.is_loop) {
that.next()
} else {
// 单曲循环
that.setData({
slider_value: 0,
current_process: '00:00',
})
audio_background_play(response)
}
})
},
// 拖动进度条,到指定位置
hanle_slider_change(e) {
const position = e.detail.value
this.seekCurrentAudio(position)
},
// 拖动进度条控件
seekCurrentAudio(position) {
// 更新进度条
let that = this wx.seekBackgroundAudio({
position: Math.floor(position),
success: function () {
AUDIOMANAGER.currentTime = position
that.setData({
current_process: format(position),
slider_value: Math.floor(position)
})
}
})
},
// 进度条滑动
handle_slider_move_start() {
this.setData({
is_moving_slider: true
});
},
handle_slider_move_end() {
this.setData({
is_moving_slider: false
});
},
// 点击播放暂停
audio_play: function () {
let that = this if (this.data.is_play) {
that.setData({
is_play: false
})
wx.pauseBackgroundAudio()
} else if (!this.data.is_play && this.data.is_ended) { // 这里是判断如果循环播放结束,没有下一首,重新播放 is_ended 是否是最后一首
audio_background_play(that.data.audio_article)
that.setData({
is_play: true,
is_ended: false
})
} else if(!this.data.is_play){
that.setData({
is_play: true
})
wx.playBackgroundAudio()
}
AUDIO.is_play = !AUDIO.is_play
},
// 点击是否循环
play_loop: function () {
let that = this if (this.data.is_loop) {
that.setData({
is_loop: false
})
} else {
that.setData({
is_loop: true
})
}
}, // 上一首
prev: function () {
let that = this if (that.data.audio_article.preArticleId != 0) {
wx.redirectTo({
url: '/pages/audio_article/audio_article?articleId=' +
that.data.audio_article.preArticleId
})
}
},
// 下一首
next: function () {
let that = this if (that.data.audio_article.nextArticleId != 0) {
wx.redirectTo({
url: '/pages/audio_article/audio_article?articleId=' +
that.data.audio_article.nextArticleId
})
} else { // 如果是最后一首
that.setData({
is_play: false,
slider_value: 0,
current_process: '00:00',
is_ended: true
})
AUDIO.is_play = false
}
},
onUnload: function () {
// 动态切换悬浮按钮的动态
if (AUDIO.is_play) {
APP.globalData.is_active = true
} else {
APP.globalData.is_active = false
}
}
})
// 时间格式化
function format(t) {
let time = Math.floor(t / 60) >= 10 ? Math.floor(t / 60) : '0' + Math.floor(t / 60) t = time + ':' + ((t % 60) / 100).toFixed(2).slice(-2)
return t
}
// 音频播放
function audio_background_play(response) {
AUDIOMANAGER.src = response.urlCompressed ? response.urlCompressed : response.audioLink // 音频的数据源,默认为空字符串,当设置了新的 src 时,会自动开始播放 ,目前支持的格式有 m4a, aac, mp3, wav
AUDIOMANAGER.title = response.articleName // 音频标题
AUDIOMANAGER.epname = response.lessonName // 专辑名
AUDIOMANAGER.singer = '****' // 歌手名
AUDIOMANAGER.coverImgUrl = response.poster // 封面图url
}
  • app.js
  globalData: {
userInfo: null,
global_bac_audio_manager: {
manage: wx.getBackgroundAudioManager(),
is_play: false,
id: '',
play_time: '',
article_id: '',
}
}

总结: 在IOS端 背景音频播放必须设置title 才可以播放

微信小程序自定义音频组件,自定义滚动条,单曲循环,循环播放的更多相关文章

  1. 微信小程序的 音频 组件

    audio:音频组件, api 接口为 wx.createInnerAudioContext audio 组件的属性: id:类型 字符串 audio 组件的唯一标识 src:类型 字符串 要播放音频 ...

  2. [小程序开发] 微信小程序audio音频播放组件+api_wx.createAudioContext

    引言: audio是微信小程序中的音频组件,可以轻松实现小程序中播放/停止音频等自定义动作. 附上微信小程序audio组件的相关属性说明:https://mp.weixin.qq.com/debug/ ...

  3. 微信小程序中的组件使用1

    不管是vue还是react中,都在强调组件思想,同样,在微信小程序中也是使用组件思想来实现页面复用的,下面就简单介绍一下微信小程序中的组件思想. 组件定义与使用 要使用组件,首先需要有组件页面和使用组 ...

  4. 原创:WeZRender:微信小程序Canvas增强组件

    WeZRender是一个微信小程序Canvas增强组件,基于HTML5 Canvas类库ZRender. 使用 WXML: <canvas style="width: 375px; h ...

  5. 微信小程序之swiper组件高度自适应

    微信小程序之swiper组件高度自适应 要求: (顶部广告栏 ) 改变swiper组件的固定高度,使之随内部每张图片的高度做自适应 原理: 图片加载完之后,获取图片的原始宽高,根据宽高比,计算出适应后 ...

  6. 微信小程序基于swiper组件的tab切换

    代码地址如下:http://www.demodashi.com/demo/14010.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ...

  7. 关于微信小程序前端Canvas组件教程

    关于微信小程序前端Canvas组件教程 微信小程序Canvas接口函数 ​ 上述为微信小程序Canvas的内部接口,通过熟练使用Canvas,即可画出较为美观的前端页面.下面是使用微信小程序画图的一些 ...

  8. uni-app开发微信小程序引入UI组件库(Vant-weapp)步骤

    uni-app开发微信小程序引入UI组件库(Vant-weapp)步骤 这里以vant-weapp为例 uni-app官方文档介绍引入组件的方法 1. 新建相关目录 根目录下创建 wxcomponen ...

  9. 微信小程序校历组件

    微信小程序校历组件 校历组件,可以作为校园小程序的插件,如果觉得不错,点个star吧

  10. 微信小程序内置组件web-view的缓存问题探讨

    前言:博客或者论坛上面,还有自习亲身经历,发现微信小程序的webview组件的页面缓存问题相当严重,对开发H5的小童鞋来说应该困扰了不少.很多小童鞋硬是抓破脑袋也没有办法解决这个问题,那我们今天就来探 ...

随机推荐

  1. JavaScript模拟QQ签名(HTML5 contenteditable属性)

    例图: 一.思路 1.单击元素时,使元素可以编辑,并获得焦点 2.按下键盘检测用户编辑元素中的文本 3.监听按下Enter键操作或离开可编辑元素焦点时,更新数据库 二.代码 $(function(){ ...

  2. J2EE完全手册(一)

    为了使开发者能尽快的开发企业级的应用程序,Sun在1999年推出一种基于J2SE(用于开发桌面应的Java标准版)的开发模型:J2EE,用于开发服务器应用程序与服务的Java企业版,他运行于J2EE服 ...

  3. unbind()清除指定元素绑定效果

    定义和用法 unbind() 方法移除被选元素的事件处理程序. 该方法能够移除所有的或被选的事件处理程序,或者当事件发生时终止指定函数的运行. ubind() 适用于任何通过 jQuery 附加的事件 ...

  4. 爬虫笔记之自如房屋价格图片识别(价格字段css背景图片偏移显示)

    一.前言 自如房屋详情页的价格字段用图片显示,特此破解一下以丰富一下爬虫笔记系列博文集. 二.分析 & 实现 先打开一个房屋详情页观察一下: 网页的源代码中没有直接显示价格字段,价格的显示是使 ...

  5. 【webService客户端】webservice客户端工具

    public static Object invokeWebService(String namespaces,String url, String method, Object[] params, ...

  6. 视觉中的经典图像特征小结(一): 颜色直方图, HOG, LBP

    [普兒原创, 如有错误和纰漏欢迎指正. 更新中...] 1. 颜色直方图 颜色空间在本质上是定义在某种坐标系统下的子空间,空间中的每一个坐标表示一种不同的颜色.颜色空间的目的在于给出某种颜色标准,使得 ...

  7. VUE之搭建脚手架

    原文转自http://blog.csdn.net/Shiyaru1314/article/details/54963027 目录(?)[-] 1 安装之前需要检查是否已经安装NodeJS的环境 安装文 ...

  8. jenkins主从从服务器发布脚本执行成功但总提示失败 FATAL: Remote call on XXXX failed

    主从jenkins当调用 slave 执行编译脚本后提示如下错误,找了半天怎么也没有问题,后来忽然发现slave上java的版本和master不同,一个 1.8 一个 1.10,将slave降回1.8 ...

  9. generator自动生成代码

    idea设置generator自动生成代码: http://blog.csdn.net/sunny243788557/article/details/45166397

  10. BZOJ 1934 Vote 善意的投票(最小割+二分图)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1934 题目大意: 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题 ...