微信小程序实现音乐列表:播放、进度把控

效果:

wxml:

<!-- 音乐列表 -->
    <view class="musiclist">
        <view class="mtitle">根据您的辨识结果,为您推荐一下音乐:</view>
        <view class="list">
            <view class="{
   
   { item.flag ? 'single play' : 'single' }}" wx:for="{
   
   { devices.files }}"
                data-src="{
   
   { item.path }}" data-index="{
   
   { index }}" catchtap="playMusic">
                <image src="{
   
   { item.flag ? '/static/images/icon/stop.png' : '/static/images/icon/startplay.png' }}" />
                <text>{
   
   { item.name }}</text>
            </view>
        </view>
    </view>

    <!-- 单个播放 -->
    <view class="musicsingle" data-index="{
   
   { tabindex }}"  data-src="{
   
   { devices.files[tabindex].path }}" bindtap="playMusic">
        <view class="myimg">
            <image animation="{
   
   {animationData}}" src="/static/images/index/musicpic.png" mode="aspectFill"/>
        </view>
        <text class="musicname">{
   
   { devices.files[tabindex].name }}</text>
        <view class="myslider">
            <slider  class="slider-light" min="{
   
   { 0 }}" max="{
   
   { videoDuration }}" value="{
   
   { devices.files[tabindex].progress }}" activeColor="#944f4c" blockColor="#EFEFEF" bindchanging='sliderChange' activeColor='#E5A06D' block-size="{
   
   {12}}" block-color="#fff"/>
        </view>
        <image class="playicon"
            src="{
   
   { devices.files[tabindex].flag ? '/static/images/icon/play-y.png' : '/static/images/icon/stop-y.png' }}" />
    </view>

 wxss:

// slider滑块大小--估计得在父组件设置
.wx-slider-thumb {
  width: 15rpx!important;
  height: 15rpx!important;
  top: 10rpx!important;
  background: #fff;
}
.musiclist {
  margin-top: 30rpx;
  padding: 40rpx 36rpx;
  background: #fff;
}
.musiclist .list .single {
  display: flex;
  padding: 20rpx;
  box-sizing: border-box;
  align-items: center;
  box-shadow: 0rpx 4rpx 20rpx 0rpx rgba(193, 195, 205, 0.5);
  border-radius: 16rpx;
  margin-bottom: 24rpx;
}
.musiclist .list .single image {
  width: 40rpx;
  height: 40rpx;
  margin-right: 8rpx;
}
.musiclist .list .single text {
  color: #343A44;
  font-size: 28rpx;
}
.musiclist .list .sinle:last-child {
  margin-bottom: 0rpx;
}
.musiclist .list .play {
  background: #3974FE;
}
.musiclist .list .play text {
  color: #fff;
}
.musiclist .mtitle {
  color: #343A44;
  font-size: 30rpx;
  font-weight: bold;
  padding-left: 20rpx;
  position: relative;
  margin-bottom: 30rpx;
}
.musiclist .mtitle::before {
  width: 6rpx;
  top: 50%;
  left: 0rpx;
  content: '';
  transform: translateY(-50%);
  height: 28rpx;
  background: #E5A06D;
  border-radius: 4rpx;
  position: absolute;
}
.musicsingle {
  display: flex;
  box-sizing: border-box;
  align-items: center;
  position: relative;
  margin-top: 30rpx;
  background: #fff;
  padding: 36rpx;
}
.musicsingle .myslider {
  width: 450rpx;
}
.musicsingle .myslider .slider-light {
  margin: 0rpx;
}
.musicsingle .myimg {
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  overflow: hidden;
  margin-right: 18rpx;
  padding: 18rpx;
  background: #676767;
  box-sizing: border-box;
}
.musicsingle .myimg image {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: rgba(255, 192, 203, 0.377);
}
.musicsingle .playicon {
  width: 40rpx;
  height: 40rpx;
  margin-left: 32rpx;
}
.musicsingle .musicname {
  top: 45rpx;
  left: 145rpx;
  color: #333;
  font-weight: bold;
  position: absolute;
  font-size: 30rpx;
  font-size: 28rpx;
}

js:

数据格式---模拟musiclist数据
{
    code: "",
    flag:false,
    id: "",
    name: "",
    path: ""   , 
    progress: 0,
}
data: {
        devices: null,
        musiclist: [],
        tabindex: 0,
        // new
        videoDuration: 0, // 视频总时长
        currentTime: '', // 播放时间 
        animationData: null,
        rotateIndex: 1,
    },
methods: {
     // this.audioCtx = wx.createAudioContext('myAudio')
        playMusic(e) {
            let devices = this.data.devices //如果直接模拟的话,不需要devices。我们对接的数据是在musiclist外边有包了一个对象
            let musiclist = devices.files
            let index = e.currentTarget.dataset.index
            let src = e.currentTarget.dataset.src
            musiclist.forEach((ele, i) => {
                if (index == i) {
                    ele.flag = !ele.flag
                } else {
                    console.log("else")
                    ele.flag = false
                }
            })
            this.data.audioCtx.src = src
            if (musiclist[index].flag) {
                this.data.audioCtx.pause()
                this.data.audioCtx.play()
                // 执行旋转或者点击图片旋转(如果你想要点击就在图片上添加点击事件我默认是添加的)
                this.refreshList()
                this.data.audioCtx.onTimeUpdate(() => {
                    let currentTime = this.data.audioCtx.currentTime
                    let duration = this.data.audioCtx.duration
                    musiclist[index].progress = currentTime
                    console.log("currentTime", duration)
                    devices.files = musiclist
                    this.setData({
                        devices,
                        currentTime: currentTime,
                        videoDuration: duration
                    })
                })
            } else {
                this.data.audioCtx.pause()
                this.stopRefresh()
            }
            this.setData({
                devices,
                tabindex: index
            })

        },
        sliderChange(e) {
            let value = e.detail.value
            let devices = this.data.devices
            devices.files[this.data.tabindex].progress = value
            this.data.audioCtx.seek(value)
            this.setData({
                currentTime: value,
                devices
            })
        },
        refreshList() {
            this.timeInterval = setInterval(function () {
                let rotateIndex = this.data.rotateIndex + 1;
                this.animation.rotate(30 * (this.data.rotateIndex - 1)).step()
                let animationData = this.animation.export()
                this.setData({
                    rotateIndex,
                    animationData
                })
            }.bind(this), 1000)
        },
        // 停止旋转
        stopRefresh() {
            if (this.timeInterval > 0) {
                clearInterval(this.timeInterval)
                this.timeInterval = 0
            }
        },
},
lifetimes: {
        attached() {
            // 创建播放对象
            this.data.audioCtx = wx.createInnerAudioContext()
            this.data.audioCtx.onCanplay(() => {
                this.data.audioCtx.currentTime //监听进度变化必须有这一步
            })
            //创建动画对象
            let animationData = wx.createAnimation({
                duration: 0, //动画的时长
                timingFunction: "ease", //动画的效果      
                delay: 0, //延迟执行的时间
                transformOrigin: "50% 50%", //动画运行的基点坐标
            })
            this.animation = animationData
        },
        detached() {
            // 在组件实例被从页面节点树移除时执行
        },
    },

猜你喜欢

转载自blog.csdn.net/qq_41687299/article/details/124605917