zoukankan      html  css  js  c++  java
  • 仿网易云音乐-音乐播放歌词展示,歌词滚动,旋转唱片,和时长进度条

    <view class="m-song-bg"  
    style="background-image: url({{songDetail.al.picUrl}});filter: blur(30px);">
    </view>
    <view>
                        <view class='m-song-wrap  {{playStatus?"z-playing":"z-pausing"}}'>
                            <view class="m-song-disc">
                                <view class="m-song-turn">
                                    <view class="m-song-rollwrap">
                                        <view class='m-song-img a-circling' style="animation-play-state:{{state}}">
                                        <image class="u-img" alt="song-img" src="{{ songDetail.al.picUrl }}"></image>
                                    </view>
                                </view>
                                <view class="m-song-lgour">
                                    <view class="m-song-light a-circling" style="animation-play-state:{{state}}">
                                    
                                    </view>
                                </view>
                            </view>
                            <text wx:if="{{!playStatus}}" class="m-song-plybtn"></text>
                        </view>
                        <view class="m-song-clickarea" bindtap="playOrpause"></view>
                    </view>
    </view>
    播放音乐代码
    var requestUrl = require('../../utils/request.js')
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        palyMusicUrl: ' ',
        playTitle:' ',
        music:null,
        songDetail: null,
        playStatus: true,
        state: ' ',
      },
      playMusic: function () {
        // const music = wx.createInnerAudioContext()
        const music = wx.getBackgroundAudioManager()
        let that = this;
        that.setData({
          music: music
        });
    
        music.autoplay = true;
        music.src = this.data.palyMusicUrl;
        music.title=this.data.playTitle;
        // console.log(this.data.palyMusicUrl)
      
        
        music.onPlay(() => {
          that.setData({
            playStatus: true,
            state: ' '
          })
          this.setCurrentIndex();
        });
        music.onPause(() => {
          console.log('pause');
          that.setData({
            playStatus: false,
            state: 'paused'
          })
        });
        music.onError((res) => {
          console.log(res.errMsg)
          console.log(res.errCode)
        })
    
      },
      playOrpause: function() {
        // var that =this;
        if (this.data.playStatus) {
          this.data.music.pause();
          // console.log(this.data.playStatus);
    
    
        } else {
          // console.log(this.data.playStatus);
          this.data.music.play();
        }
      },
      onLoad: async function (options) {
        // console.log(options.title);
        // const url = `/song/detail?ids=${options.id}`;
        const url = `/song/url?id=${options.id}`;
        const res = await requestUrl.get(url);
        const res_songDetail= await requestUrl.get(songDetail);
        // const palyMusicUrl = res.data.data[0].url;
        //  console.log(res_lyric.data.lrc.lyric);
        //  console.log(res_songDetail.data.songs);
        this.setData({
          palyMusicUrl: res.data.data[0].url,
          playTitle: options.title,
          songDetail: res_songDetail.data.songs[0]
        });
        
         this.playMusic();
         this.dealLrc();
         
        // console.log(res.data);
        // this.time();
      },
     
    musicplay.js
    text {
        padding: 0;
        margin: 0;
      }
      .m-song-wrap {
        padding-top: 63px;
    }
    .m-song-disc {
        position: relative;
        width: 248px;
        height: 248px;
        margin: 0 auto;
    }
    .m-song-turn {
        width: 100%;
        height: 100%;
    }
    .m-song-turn:before {
        content: " ";
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        z-index: 2;
        background: url(//s3.music.126.net/mobile-new/img/disc.png?d3bdd10…=) no-repeat;
        background-size: contain;
    }
    .m-song-rollwrap {
        position: absolute;
        width: 150px;
        height: 150px;
        left: 50%;
        top: 50%;
        z-index: 1;
        margin: -75px 0 0 -75px;
    }
    .m-song-img {
        width: 100%;
        height: 100%;
        border-radius: 50%;
        overflow: hidden;
        background: url(//s3.music.126.net/mobile-new/img/disc_default.png?ba7c53e…=) no-repeat;
        background-size: contain;
    }
    .m-song-lgour, .m-song-light {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        z-index: 3;
    }
    .m-song-light {
        background: url(//s3.music.126.net/mobile-new/img/disc_light.png?2bb24f3…=) no-repeat;
        background-size: contain;
    }
    .m-song-plybtn {
        position: absolute;
        width: 50px;
        height: 50px;
        left: 50%;
        top: 50%;
        -webkit-transform: translate(-50%,-50%);
        -ms-transform: translate(-50%,-50%);
        transform: translate(-50%,-50%);
        z-index: 10;
        background: url(//s3.music.126.net/mobile-new/img/play_btn_3x.png?4da7e135b7c089f3777ec5cdbbb3a8d8=) 0 0 no-repeat;
        background-size: contain;
    }
    .m-song-plybtn:after {
        content: "";
        display: block;
        position: absolute;
    }
    .m-song-disc:after {
        width: 96px;
        height: 137px;
        top: -70px;
        left: 133px;
        background-image: url(//s3.music.126.net/mobile-new/img/needle-ip6.png?be4ebbe…=);
    }
    .m-song-disc:after {
        content: " ";
        position: absolute;
        top: -63px;
        left: 107px;
        z-index: 5;
        width: 84px;
        height: 122px;
        background: url(//s3.music.126.net/mobile-new/img/needle.png?702cf6d…=) no-repeat;
        background-size: contain;
    }
    .m-song-light {
        background: url(//s3.music.126.net/mobile-new/img/disc_light.png?2bb24f3…=) no-repeat;
        background-size: contain;
    }
    .m-song-bg {
        background-color: #161824;
        background-position: 50%;
        background-repeat: no-repeat;
        background-size: 150% 150%;
        -webkit-transform: scale(1.5);
        -ms-transform: scale(1.5);
        transform: scale(1.5);
        -webkit-transform-origin: center;
        -ms-transform-origin: center;
        transform-origin: center;
        position: fixed;
        left: 0;
        right: 0;
        top: 0;
        height: 100%;
        overflow: hidden;
        z-index: 1;
        
    }
    .m-song-bg:before {
        content: " ";
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        top: 0;
        background-color: rgba(0,0,0,.7);
    }
    .m-song-clickarea {
        position: absolute;
        width: 100%;
        top: 0;
        left: 0;
        bottom: 200px;
        z-index: 10;
        margin-bottom: env(safe-area-inset-bottom);
    }
    .u-img {
        width: 100%;
        vertical-align: middle;
    }
    .aboutsougou {
        display: none;
    }
    .m-song-info {
        padding: 0 35px;
        margin-top: 25px;
        position: relative;
        z-index: 20;
        text-align: center;
    }
    .m-song-h2 {
        font-size: 18px;
    }
    .m-song-h2 {
        text-align: center;
        line-height: 1.1;
        color: #fefefe;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    .m-song-autr, .m-song-pure {
        font-size: 16px;
    }
    .m-song-autr {
        color: hsla(0,0%,100%,.6);
    }
    .m-song-lrc {
        position: relative;
        margin-top: 14px;
    }
    .m-song-scroll {
        line-height: 1.5;
        font-size: 13px;
        /* height: 50px; */
        overflow: hidden;
        -webkit-mask: -webkit-linear-gradient(top,#000,#000 70%,rgba(0,0,0,0));
    }
    .m-song-lremp, .m-song-scroll {
        text-align: center;
        color: hsla(0,0%,100%,.6);
    }
    .m-song-lritem {
        /* display: inline-flex; */
        height: 32px;
        line-height: 32px;
        
    }
    /* animation css  */
    .a-circling {
        -webkit-animation: circling 20s linear infinite;
        animation: circling 20s linear infinite;
    }
    .pause{
        animation-play-state:paused;
    }
    @keyframes circling {
        from {transform: rotateZ(0deg);}
        to {transform: rotateZ(360deg);}
    }
    
    @-webkit-keyframes circling {
        from {-webkit-transform: rotate(0deg);
        }
        to {-webkit-transform: rotate(360deg);}
    }
    .m-song-iner {
        -webkit-transition: -webkit-transform .5s ease-out;
        transition: -webkit-transform .5s ease-out;
        transition: transform .5s ease-out;
        transition: transform .5s ease-out,-webkit-transform .3s ease-out;
    }
    /*进度条长度  */
    .slid{
        display: flex;
        position: relative;
        z-index: 10;
        justify-content: space-between;
        padding: 50rpx 20rpx;
      }
      .slid view{
        
        font-size: 32rpx;
        color: #999;
      }
      slider{
        width: 500rpx;
        margin: 0 20rpx;
        border-radius:5rpx;
        
      }
    musicplay.wxss

    唱片旋转的效果使用CSS3动画。唱片随歌曲播放和暂停。

    <view class="m-song-light a-circling" style="animation-play-state:{{state}}">

     设定state的状态,‘ ’或者‘pause’

    music.onPlay(() => {
          that.setData({
            playStatus: true,
            state: ' '
          })
          this.setCurrentIndex();
        });
        music.onPause(() => {
          console.log('pause');
          that.setData({
            playStatus: false,
            state: 'paused'
          })
        });

    2. 播放slide采用了微信小程序的表单组件silder

    <view class="slid">
        <view>
            <text class='times'>{{currentTime}}</text>
        </view>
        <slider bindchange="sliderChange" activeColor="#d33a31" block-size="12" backgroundColor="#999" value="{{percent}}" >
        </slider>
        <view>
            <text class='times'>{{duration}}</text> 
        </view>
    </view>

    获取数据:currentTime duration

    处理数据:percent

    data: {
        currentTime:'00:00',
        duration:' ',
        percent:' ',
      }
    formatTime: function(time) {
         var minute =Math.ceil(time/60)%60;
         var sec = Math.ceil(time)%60;
         return (minute<10? '0'+minute : minute) + ':' + (sec<10 ? '0' +sec : sec)
      },
    music.onTimeUpdate(() =>{
          let duration = that.formatTime(music.duration);
          let currentTime = that.formatTime(music.currentTime);
          let percent =(music.currentTime/music.duration*100).toFixed(2);
          // console.log(music.duration +'--'+ percent +'--'+ music.currentTime);
          that.setData({
            duration:duration,
            currentTime: currentTime,
            percent:percent,
            musicTime:parseInt(music.currentTime)
          });
        });

    //滑块滑动jS
    sliderChange: function(e) { 
        var that=this;
        // that.data.music.pause();
     
        let slideValue = e.detail.value;
        let  seeKPosition = that.data.music.duration/100*slideValue
         that.data.music.seek(seeKPosition);
        // console.log(currentTime)
         setTimeout(function () {
           that.data.music.play();
           }, 500);   
      },
     

    获取歌词并设定歌词滚动

    //歌词处理,得到的歌词需要经过处理才能使用
    dealLrc: function(lrc) {
        // let lrc = this.data.musicLyric;
        var that=this;
        var arr = lrc.split("
    ");
        var timeArr = [], lrcArr = [];
        arr.forEach(function (item, index) {
          var time = item.slice(item.indexOf("["), item.indexOf("]") + 1);
          time = that.dealLrcTime(time);
          timeArr.push(time);
          var lrc = item.substr(item.indexOf("]") + 1)+"
    ";
          lrcArr.push(lrc);
          // console.log(time)
        });
        // console.log(lrcArr)
        // console.log(timeArr)
        that.setData({
          lyrics: lrcArr,
          lyricsTime:timeArr
        });
      },
      dealLrcTime: function(time) {
        time = time.replace("[", "");
        time = time.replace("]", "");
        var arr = time.split(":");
        var relTime = parseInt(arr[0]) * 60 + parseInt(arr[1]);
        return relTime;
      },
      //找到当前播放时间
      findCurrentIndex(curTime,timeArr) {
        // var curTime = this.data.musicTime;
        // var timeArr = this.data.lyricsTime;
        var index = -1;
        for (let i = 0; i < timeArr.length; ++i) {
          if (timeArr[i] == NaN) {
            continue;
          }
          if (curTime <= timeArr[i]) {
            index = i;
            break;
          }
        }
        return index;
        
      },
    //设置当前歌曲播放的位置
      setCurrentIndex:function(){
        var timeId=wx.getStorageSync("timeId");
        if(timeId){
          clearInterval(timeId);
        }
        if(this.data.musicLyric){
          // var audio = this.data.audio;
          // var duration = audio.duration;
          var timeArr = this.data.lyricsTime;
          var currentTime = -1;
          var that = this;
          timeId = setInterval(() => {
            currentTime = that.data.musicTime;
            var currentIndex =that.findCurrentIndex(currentTime, timeArr);
           this.setData({
              currentIndex: currentIndex
            });
    
          }, 2000);
          wx.setStorageSync("timeId", timeId);
        }
        
      },
    
    onLoad: async function (options) {
        // console.log(options.title);
        // const url = `/song/detail?ids=${options.id}`;
        var that=this;
        const url = `/song/url?id=${options.id}`;
        const lyric=`/lyric/?id=${options.id}`;
        const songDetail=`/song/detail?ids=${options.id}`;
        const res = await requestUrl.get(url);
        const res_lyric= await requestUrl.get(lyric);
        const res_songDetail= await requestUrl.get(songDetail);
        const musicLyric = that.dealLrc(res_lyric.data.lrc.lyric);
        // const palyMusicUrl = res.data.data[0].url;
        //  console.log(res_lyric.data.lrc.lyric);
        //  console.log(res_songDetail.data.songs);
        this.setData({
          palyMusicUrl: res.data.data[0].url,
          playTitle: options.title,
          // musicLyric: res_lyric.data.lrc.lyric,
          songDetail: res_songDetail.data.songs[0]
        });
        
         this.playMusic();
        //  this.dealLrc();
         
        // console.log(res.data);
        // this.time();
      },
                    <view>
                        <view style="position:relative">
                            <view class="m-song-info">
                                <h2 class="m-song-h2">
                                    <text class="m-song-sname">{{songDetail.name}}</text>
                                    <text class="m-song-gap">-</text>
                                    <b class="m-song-autr">{{songDetail.ar[0].name}}</b>
                                </h2>
                                <view class="m-song-lrc f-pr">
                                    <view class="m-song-scroll" >
                                        <view class="m-song-iner"  style="transform: translateY(-{{32*currentIndex}}px);">
                                            <block wx:for="{{lyrics}}" wx:key="index" wx:for-index="i" >
                                                <view class="m-song-lritem j-lritem" style='{{i==currentIndex?"color: rgb(255, 255, 255);":" "}}'>
                                                    {{item}}
                                                </view>
                                            </block>
                                        </view>
                                    </view>
                                </view>
                            </view>
                        </view>
                        <view class="m-link m-music-street" style="margin-top: 15px;">
                            <view class="m-musicStreetWakeUp">
                                <image src=""></image>
                            </view>
                        </view>
                    </view>

    歌词滚动,获取当前所在的歌词位置,CSS控制歌词向上滚动

  • 相关阅读:
    利用LibreOffice进行WORD转PDF
    SpringBoot实践
    Solr学习笔记(一)
    HashMap原理(转)
    PDF.js展示本地文件
    设计模式之代理模式
    (一)DUBBO基本学习
    如何架构一个框架
    冒泡排序
    js 函数传数组参数
  • 原文地址:https://www.cnblogs.com/cheryshi/p/14781536.html
Copyright © 2011-2022 走看看