热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微信小程序自定义音频组件,自定义滚动条,单曲循环,循环播放

小程序自定义音频组件,带滚动条摘要:首先自定义音频组件,是因为产品有这样的需求,需要如下样式的而微信小程序API给我们提供的就是这样的而且产品需要小程

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

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

而微信小程序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

    
    
    
        {{current_process}}
        
        {{total_process}}
    
    
        
        
        
        
    
滑动事件 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 才可以播放


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了10分钟了解Android的事件分发相关的知识,希望对你有一定的参考价值。什么是事件分发?大家 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 本文介绍了贝叶斯垃圾邮件分类的机器学习代码,代码来源于https://www.cnblogs.com/huangyc/p/10327209.html,并对代码进行了简介。朴素贝叶斯分类器训练函数包括求p(Ci)和基于词汇表的p(w|Ci)。 ... [详细]
  • android 触屏处理流程,android触摸事件处理流程 ? FOOKWOOD「建议收藏」
    android触屏处理流程,android触摸事件处理流程?FOOKWOOD「建议收藏」最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到A ... [详细]
  •  项目地址https:github.comffmydreamWiCar界面做的很难看,美工方面实在不在行。重点是按钮触摸事件的处理,这里搬了RepeatListener项目代码,例 ... [详细]
  • 涉及的知识点-ViewGroup的测量与布局-View的测量与布局-滑动冲突的处理-VelocityTracker滑动速率跟踪-Scroller实现弹性滑动-屏幕宽高的获取等实现步 ... [详细]
author-avatar
缘zhi韵_297
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有