书接上回,我们先来美化一下播放页面

songplay.wxml

<view>
  <image id="needle" src="../../public/needle.png"></image>
</view>
<view id="playPage">
  <image id="turntable" src="https://s3.music.126.net/mobile-new/img/disc-ip6.png?6979612%E2%80%A6="></image>
  <image class="coverImg"
    src="http://p1.music.126.net/q2ag5aifgDZqAOm6GLkc_g==/109951165165020942.jpg?imageView&quality=89"></image>
  <image id="playStatus" src="../../public/playBtn.png"></image>
</view>

<view id="control">
  <image id="left" src="../../public/last.png"></image>
  <image id="middle" src="../../public/play.png" bindtap="play"></image>
  <image id="right" src="../../public/next.png"></image>
</view>

wxss

这里又出现了#,#表示一个id,.表示一个类,id和类的一个区别就是id只能给一个标签,而类可以给多个标签

page{
  background-color: #161824;
}
#needle{
  position: absolute;
  width: 96px;
  height: 137px;
  left: 50%;
  z-index: 10;
}
#playPage{
  width: 290px;
  height: 290px;
  position: relative;
  left: 50%;
  transform: translate(-50%,20%);
}
.coverImg{
  position: absolute;
  width:160px;
  height:160px;
  border-radius: 100%;
  left: 50%;
  top: 50%;
  margin-left: -80px;
  margin-top: -80px;
}
#playStatus{
  position: absolute;
  width: 50px;
  height: 50px;
  z-index: 10;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}
#turntable{
  position: absolute;
  width: 290px;
  height: 290px;
}

#control{
  position: absolute;
  width: 100%;
  bottom: 10%;
  height: 60px;
}
#control image{
  position: absolute;
  width: 60px;
  height: 60px;
}
#control #left{
  left: 20%;
}
#control #right{
  right: 20%;
}
#control #middle{
  left: 50%;
  transform: translate(-50%,0);
}

现在点击是没有任何效果的,我们给封面制作一个旋转的动画,让点击中间播放按钮可以让播放键变成暂停键而且封面里的播放键消失

旋转效果

songplay.wxss

@keyframes coverRotate{
  0%{
    transform: rotate(0deg);
  }
  100%{
    transform: rotate(360deg);
  }
}
.coverImgPlay{
  animation: coverRotate 2s linear infinite;
}

第一段表示创建一个名为coverRotate的关键帧动画,从0到100两个关键帧,动作分别是旋转0度和旋转360度

第二段表示给coverImgPlay这个类增加一个动画属性,动画属性值为coverRotate这个帧动画,持续两秒,线性动画,无限循环

但是现在先不加,后面通过点击播放按钮控制动画的播放

在playpage.js中定义两个变量

playStatus表示是否正在播放音乐

middle表示中间按钮的图片地址(因为要让播放和暂停两个按钮图片切换)

data: {
    playStatus:false,
    middleImg:'../../public/play.png'
  },

写一个点击事件

play(e){
    var status=this.data.playStatus;
    if (status) {
      this.setData({
        playStatus:false,
        middleImg:'../../public/play.png',
      })
    }else{
      this.setData({
        playStatus:true,
        middleImg:'../../public/stop.png',
      })
    }
  },

playpage.wxml中绑定事件,并把src属性改为middleImg

点击按钮就能切换图片了

给封面图加上一句

wx:if=“{{playStatus}}”,这一句表示如果playStatus为true,就渲染这个image标签,否则就不渲染

所以我们在js里动态修改playStatus的值时,就会动态渲染页面(vue的特性之一)

还可以用三元运算符,如果playStatus为true就返回coverImgPlay这个类给image标签,否则就返回空,所以相当于给image增加了一个自旋转的类

音乐的播放

在网易云网页上获取音乐地址有点麻烦,所以我们借助一下第三方工具

https://www.jbsou.cn/

在这里输入音乐名字,就可以获得音乐的真实链接

所以现在记住这个链接

我们在onload函数里写几行代码,让页面加载时自动播放音乐

打开songplay.js,有一个onload函数,这个函数是当页面被初次加载时调用的

关于createInnerAudioContext的文档:https://developers.weixin.qq.com/miniprogram/dev/api/media/audio/InnerAudioContext.html

下面的第二行表示创建一个音乐文件,autoplay设置自动播放,loop设定循环,src设定音乐地址

最后调用play方法播放音乐

  onLoad: function (options) {
    var audio = wx.createInnerAudioContext();
    audio.autoplay = true;
    audio.loop = true;
    audio.src = "http://music.163.com/song/media/outer/url?id=519909841.mp3";
    audio.play();
  },

现在我们进入播放页面就会自动播放音乐了

但是我们反复进入退出播放页面就会有一个问题,每次进入这个页面都会播放音乐,先前的音乐不会停止,这样就会很嘈杂,所以我们返回时让音乐停止播放

我们发现下面有一个onunload方法,这个方法在退出页面时调用,所以我们在这里写代码让音乐停止

但是我们上面写的audio是一个局部变量,在别的函数里是访问不到的,所以我们定义一个全局变量用来管理音乐

初始化audio时把它赋值给audioContex

这样进入页面就会播放音乐,退出就会停止

下面我们将按钮和音乐联动起来

因为按钮默认状态是三角形,所以一开始先不要播放音乐,把这一句去掉,把自动播放改成false

然后我们之前写了改变按钮状态的play函数,我们在这里控制音乐的暂停与播放

逻辑是 如果点击按钮时播放状态是false,说明没有播放音乐,所以音乐播放,如果是true则反之

  play(e) {
    var status = this.data.playStatus; //获取data中playstatus值
    if (status) {
      this.setData({ //设定data中的变量值
        playStatus: false,
        middleImg: '../../public/play.png',
      })
      this.data.audioContex.pause();
    } else {
      this.setData({
        playStatus: true,
        middleImg: '../../public/stop.png',
      })
      this.data.audioContex.play();
    }
  },

现在我们已经能够正常播放一首歌了,那如果根据点击音乐的不同,播放不同的音乐该怎么做(我们现在播放哪个音乐时写死的)我们先优化之前的音乐列表界面,现在只能显示一个音乐信息,我们让它能够动态生成更多的音乐信息

我们现在songlist.js中增加存储音乐信息的json(javascript存储信息的一种格式)

data: {
    "songList": [
      {
        "songName": "70億のピース",
        "singer": "秦基博",
        "url": "http://p1.music.126.net/ssKtJQMehHO1_xTs3n0DZw==/109951163097041912.jpg?param=130y130",
        "src": "http://music.163.com/song/media/outer/url?id=1368865170.mp3"
      },
      {
        "songName": "私へ",
        "singer": "supercell",
        "url": "http://p2.music.126.net/vBq3ttdbWrVIVnXaVcfDug==/803742999928373.jpg?param=130y130",
        "src": "http://music.163.com/song/media/outer/url?id=22709625.mp3"
      },
      {
        "songName": "何もかも有り余っている こんな時代も",
        "singer": "Goose house",
        "url": "http://p2.music.126.net/2i1igcfXAYRJN9qf_LnWbA==/109951163067866087.jpg?param=130y130",
        "src": "http://music.163.com/song/media/outer/url?id=519909841.mp3"
      }
    ]
  },

修改songlist.wxml

wx:for表示遍历songlist这个数组,wx:key把当前循环中的songList数组内容赋值给item,下面的index表示循环下标(0开始)

比如我们有三次循环,三次循环中item分别等于songList[0],songList[1],songList[2],index就分别表示0,1,2

同样我们使用{{}}将变量括起来,引用item的内容

这样页面上的歌曲信息就会和我们js里面写的一致了

点击播放按钮时也要将歌曲列表信息传送给播放页面

我们修改之前写的播放按钮的事件

我们写一句data-pid={{index}}

然后修改playBtnClick方法

这里的dataset.pid就是上面我们设定的data-pid值,也就是index

  playBtnClick:function(e){
    var id=e.currentTarget.dataset.pid;
    wx.navigateTo({
     url: '/pages/songplay/songplay?index='+id+'&list='+encodeURIComponent(JSON.stringify(this.data.songList)),
   })
  },

问号后面表示我们在不同页面间传递的参数

因为我们也要把歌曲列表信息传输过去,所以要把json格式转换为字符串,而歌曲名可能是中文或别的,而且歌曲信息很长,所以用到encodeURIComponent方法

点击列表界面的播放按钮时,会把数据传输到播放界面,也就是songplay.js的onLoad方法里面(options参数)

有编码就有解码,所以这里要把之前编码成字符串的json再解码成json

这样点击不同列表项就可以播放不同的音乐了

Last modification:November 14th, 2020 at 10:08 pm