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


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

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

    而微信小程序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;
         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;
         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- 100% !important;
    }
    
    .audio .poster {
         238rpx;
        height: 336rpx;
    }
    /* 音频滚动条start */
    .control-process {
        margin-top: 20rpx;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .control-process .slider {
         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 {
         64rpx;
        height: 64rpx;
        vertical-align: middle;
    }
    
    .audio .audio-play {
         92rpx;
        height: 92rpx;
    }
    
    .audio .pattern {
        position: absolute;
        top: 0;
        bottom: 0;
        margin: auto 0;
         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 才可以播放

  • 相关阅读:
    BZOJ5311,CF321E 贞鱼
    POJ3208 Apocalypse Someday
    POJ1037 A decorative fence
    POJ1737 Connected Graph
    CF559C Gerald and Giant Chess
    NOI2009 诗人小G
    Problem 2726. -- [SDOI2012]任务安排
    POJ1821 Fence
    HDU5542 The Battle of Chibi
    POJ2376 Cleaning Shifts
  • 原文地址:https://www.cnblogs.com/luxiaoyao/p/9371366.html
Copyright © 2020-2023  润新知