Applet del reproductor de música WeChat

Uno: Objetivos de aprendizaje:

  1. Domine el uso de componentes de swiper y componentes de vista de desplazamiento;
  2. Dominar el uso de componentes de imagen;
  3. Domina el uso de componentes deslizantes;
  4. Domina el uso de la API de audio;

 Dos: Directorio:

1. Preparación antes del desarrollo

1.1 Visualización del proyecto del applet de música :

1.1.1: Pantalla de interfaz de recomendación de música :

1.1.2: Visualización de la interfaz del reproductor :

1.1.3: Visualización de la interfaz de la lista de reproducción :

1.2: Análisis del proyecto :

①: Proyecto de reproductor de música (diagrama de estructura del proyecto)

  • barra de navegación de pestañas
  • área de contenido
  • control de reproducción de música del reproductor

 ②: Los archivos principales del proyecto del applet del reproductor de música :

  • app.js : el archivo lógico de la aplicación
  • app.json : archivo de configuración de la aplicación
  • pages/index/index1.js : el archivo lógico de la página de índice
  • pages/index/index1.json : archivo de configuración para la página de índice
  • pages/index/index1.wxss : el archivo de estilo de la página de índice
  • pages/index/index1.wxml : el archivo de estructura de la página de índice
  • pages/index/info.wxml : El archivo de estructura de la pestaña "Recomendación musical"
  • pages/index/play.wxml : El archivo de estructura de la pestaña "Reproductor"
  • pages/index/playlist.wxml : El archivo de estructura de la pestaña "Lista de reproducción"
  • imágenes : archivos de imagen

 1.3: Inicialización del proyecto :

Las herramientas del desarrollador crean un proyecto:

2. Cambio de pestaña 

2.1: Análisis de tareas:

Diagrama de estructura de página y página de pestañas:

2.2  Conocimientos preliminares:

Propiedades comunes de los componentes del swiper:

valor opcional

ilustrar

por defecto

puntos indicadores

booleano

Ya sea para mostrar el punto indicador del panel, el valor predeterminado es falso

indicador-color

Color

Color del puntero, el valor predeterminado es rgba (0,0,0, .3)

indicador-activo-color

Color

El color de punto actualmente seleccionado, el valor predeterminado es #000000

auto-reproducción

booleano

Ya sea para cambiar automáticamente, el valor predeterminado es falso

actual

Número

El índice del control deslizante actual, el valor predeterminado es 0

id-elemento-actual

Cadena

El ID de elemento del control deslizante actual (no se puede especificar el actual al mismo tiempo)

intervalo

Número

Intervalo de cambio automático (milisegundos), el valor predeterminado es 5000

duración

Número

Duración de la animación de la diapositiva (milisegundos), el valor predeterminado es 500

circular

booleano

Ya sea para usar deslizamiento conjunto, el valor predeterminado es falso

vertical

booleano

Si la dirección de deslizamiento es vertical, el valor predeterminado es falso

cambio de enlace

EventHandle

El evento de cambio se activa cuando cambia la corriente

El componente swiper escribe la estructura de página deslizante index1.wxml (este proyecto se ha completado, no existe tal código)

③: incluye el propósito principal:

  • Dividir su código en varios archivos hace que sea más fácil encontrar su código.
  • Extraiga las partes comunes del código. Introducido a través de archivos externos.

④: Escribir estructura y estilo de página - barra de navegación de pestañas  

 2.3 Estructura y estilo de la página de escritura:

①: La página básica y el estilo del subprograma de música:

②: La página básica y el estilo del subprograma de música - el estilo de la navegación por pestañas:

 Efecto de estilo de navegación de pestañas:

 2.4: Implementar el cambio de pestaña:

Haga clic en la pestaña de la barra de navegación para lograr el cambio de pestaña (js):

Cambie los efectos de página a través de eventos de desplazamiento (js):

 Efecto:

 3. Recomendación musical

3.1 Análisis de tareas

Diagrama de estructura de la página de recomendaciones musicales:

3.2 Conocimientos preliminares 

Propiedades y descripción del componente de imagen:

valor opcional

ilustrar

por defecto

origen

Cadena

Dirección de recurso de imagen

modo

Cadena

Modo de recorte y escalado de imágenes, el valor predeterminado es 'scaleToFill'

Carga lenta

booleano

Si la imagen está cargada de forma diferida, el valor predeterminado es falso. Solo válido para imágenes debajo de la página y vista de desplazamiento

enlazar error

ManejarEvento

Evento cuando ocurre un error de imagen

carga enlazada

ManejarEvento

Evento cuando se completa la carga de la imagen

escalar para llenar

Escala la imagen sin mantener la relación de aspecto, de modo que el ancho y el alto de la imagen se estiren por completo para llenar el elemento de la imagen. Aplicable al caso en que el contenedor tenga la misma relación de aspecto que la imagen, de lo contrario la imagen se distorsionará.

aspectoFit

Escala la imagen manteniendo la relación de aspecto para que el lado largo de la imagen se muestre completamente. Es adecuado para mostrar la imagen por completo. Por ejemplo, la imagen de la página de detalles.

relleno de aspecto

Mantenga la relación de aspecto para hacer zoom en la imagen, solo asegúrese de que el lado corto de la imagen se pueda mostrar completamente y el lado largo sea interceptado. Aplicable a la situación en la que el contenedor está fijo y la imagen se escala automáticamente, como la miniatura de la página de lista

anchoFijar

El ancho permanece sin cambios, la altura cambia automáticamente y la relación de aspecto de la imagen original permanece sin cambios

arriba

No escalar la imagen, solo mostrar la zona superior de la imagen

abajo

No escalar la imagen, solo mostrar la zona inferior de la imagen

centro

No haga zoom en la imagen, solo muestre el área central de la imagen

izquierda

No haga zoom en la imagen, solo muestre el área izquierda de la imagen

bien

No haga zoom en la imagen, solo muestre el área derecha de la imagen

arriba a la izquierda

No haga zoom en la imagen, solo muestre el área superior izquierda de la imagen

parte superior derecha

No haga zoom en la imagen, solo muestre el área superior derecha de la imagen

abajo a la izquierda

No haga zoom en la imagen, solo muestre el área inferior izquierda de la imagen

abajo a la derecha

No haga zoom en la imagen, solo muestre el área inferior derecha de la imagen

Modo de escala de componentes de imagen y prueba de modo de recorte (imagen de efecto):

3.3  Imagen del carrusel

Use el componente swiper en info.wxml para implementar el carrusel:

3.4  Botones de función 

El diseño flexible realiza el botón de función:

estilo de diseño flexible:

 Representaciones:

3.5  Música caliente 

①: el diseño flexible realiza el diseño de la página:

  El diseño flexible realiza el diseño de página (estilo):

②: Reproducir en la parte inferior de la página de índice:

Reproducir en la parte inferior de la página de índice (estilo):

El efecto de representación en la parte inferior de la reproducción de la página de índice:

4. jugador

4.1 Análisis de tareas

4.1.1 Analizar las funciones específicas del jugador:

  • Información de música: muestra el título y el artista de la pista que se está reproduciendo actualmente.
  • Carátula del álbum: cuando se reproduce la música, la carátula del álbum girará en el sentido de las agujas del reloj.
  • Progreso de la reproducción: muestra el progreso de la reproducción y ajusta el progreso de la música. 

4.1.2 Diagrama de la estructura de la página de la pestaña del jugador:

4.2 Conocimientos preliminares

①: Propiedades y descripción de la interfaz API de audio:

valor opcional

nombre

ilustrar

Atributos

origen

La dirección del recurso de audio, utilizada para la reproducción directa.

hora de inicio

La posición inicial (segundos), el valor predeterminado es 0

auto-reproducción

Ya sea para comenzar a jugar automáticamente, el valor predeterminado es falso

bucle

Ya sea para hacer un bucle, el valor predeterminado es falso

volumen

volumen. El rango es 0~1. El valor predeterminado es 1

Atributos

duración

La duración del audio en segundos. Devuelve cuando actualmente hay un src válido (solo lectura)

tiempo actual

La posición de reproducción (en segundos) del audio. Devuelve cuando actualmente hay un src válido (solo lectura)

en pausa

Si el estado actual está en pausa o detenido (solo lectura)

método

jugar()

jugar

pausa()

Pausa (el audio en pausa comenzará a reproducirse desde el punto en pausa)

detener()

Detener (la reproducción de audio después de detenerse comenzará desde el principio)

buscar()

Saltar a la ubicación especificada

destruir()

destruir la instancia actual

onCanplay()

El evento de que el audio ingrese al estado reproducible (el parámetro es una función de devolución de llamada)

enReproducir()

Evento de reproducción de audio (el parámetro es una función de devolución de llamada)

método

en pausa ()

Evento de pausa de audio (el parámetro es una función de devolución de llamada)

onStop()

Evento de parada de audio (el parámetro es una función de devolución de llamada)

al Terminar()

El evento de que el audio se reproduzca naturalmente hasta el final (el parámetro es una función de devolución de llamada)

enBuscado()

El evento de la operación de salto de audio (el parámetro es una función de devolución de llamada)

onTimeUpdate()

Evento de actualización del progreso de la reproducción de audio (el parámetro es una función de devolución de llamada)

onError()

Evento de error de reproducción de audio (el parámetro es una función de devolución de llamada)

②: uso del caso innerAudioContext:

③: Propiedades y descripción del componente del control deslizante:

valor opcional

tipo

ilustrar

min

Número

Valor mínimo, el valor predeterminado es 0

máximo

Número

Valor máximo, el valor predeterminado es 100

paso

Número

Tamaño de paso, el valor es mayor que 0, divisible por (máximo-mínimo), el valor predeterminado es 1

valor

Número

El valor actual, el valor predeterminado es 0

coloractivo

Color

El color seleccionado, por defecto es #1aad19

color de fondo

Color

El color de la barra de fondo, por defecto es #e9e9e9

tamaño de bloque

Número

El tamaño del control deslizante, el rango de valores es 12 ~ 28, el valor predeterminado es 28

bloque de color

Color

El color del control deslizante, por defecto es #ffffff

Mostrar valor

booleano

Ya sea para mostrar el valor actual, el valor predeterminado es falso

cambio de enlace

EventHandle

Evento desencadenado después de que se completa un arrastre

cambio de enlace

EventHandle

Eventos desencadenados durante el arrastre

4.3 Definir datos básicos

4.4 Realizar la función de reproducción de música

①:音乐播放逻辑代码(js):

②:底部播放器暂停/播放按钮控制歌曲:

js:

③:播放器切换到下一首歌曲:

js:

4.5 编写播放器页面

①:播放页面 play.wxml 结构代码:

播放页面样式代码:

效果:

②:播放器样式代码:

③:通过样式动画实现海报的旋转功能:

海报的旋转功能样式代码:

4.6 控制播放进度

播放器页面下方的滑块结构(play.wxml中):

滑块样式代码:

5. 播放列表

5.1 任务分析结构图

5.2 编写页面结构和样式

控制进度条的长度控制歌曲播放进度:

控制进度条的长度控制歌曲播放进度样式:

5.3 实现换曲功能

换曲功能(js)代码:

代码:

pages/index/index1.js:

// pages/index/index1.js
Page({
  /**
   * 页面的初始数据
   * item控制页面显示的,0-2,表示显示不同的页面和顶部不同的导航
   *  state控制图标或当前音乐播放的状态:'paused'表示暂停,'running'表示在运行
   */
  data: {
    item:2,
    state:'paused',
    playindex:0,
    playlist:[{
      id:1,
      title:"운명(命运)",
      singer:"why",
      coverImage:"../images/cover.jpg",
      src:"http://www.ytmp3.cn/down/78392.mp3"
    },{
      id:2,
      title:"玫瑰花的葬礼",
      singer:"许嵩",
      coverImage:"../images/cover.jpg",
      src:"http://www.ytmp3.cn/down/78393.mp3"
    },{
      id:3,
      title:"小酒窝",
      singer:"蔡卓妍/林俊杰",
      coverImage:"../images/cover.jpg",
      src:"http://www.ytmp3.cn/down/78378.mp3"
    },{
      id:4,
      title:"十年",
      singer:"陈奕迅",
      coverImage:"../images/cover.jpg",
      src:"http://www.ytmp3.cn/down/78384.mp3"
    }],
    currentplay:{
      id:0,
      title:"",
      singer:"",
      coverImage:"",
      src:"",
      duration:"00:01",
      currentTime:"00:01",

    }

  },
  changeItem:function(e){
   
    this.setData({
      item:e.target.dataset.item
    })

  },
  changeTab:function(e){
    console.log(e)
    this.setData({
      item:e.detail.current
    })
  },
  play:function(e){
    // 还缺音乐播放里面暂停播放的逻辑
    this.audioCtx.play();
    this.setData({
      state:'running'
    })
  },
  pause:function(e){
    // 还缺音乐播放里面暂停播放的逻辑
    this.audioCtx.pause();
   this.setData({
     state:'paused'
   })
  },
  next:function(e){
    var index = this.data.playindex
    var count = this.data.playlist.length;
    index = index +1;
    index = index%count;
    this.setMusic(index)
    this.play()
  
  },
  changeMusic:function(e){
    console.log(e)
    var index = e.currentTarget.dataset.index;
    this.setMusic(index);
    this.play();

  },
  scroll: function(e) {
    console.log(e.detail)
  },
  testBind:function(e){
    console.log(e)
  } ,
  testBinding:function(e){
    console.log(e)
  } ,
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  audioCtx:null,
  onReady() {
    this.audioCtx = wx.createInnerAudioContext();
    this.setMusic(0);//默认选择第一首
    var outthis = this;
    this.audioCtx.onTimeUpdate(function(){
      var duration = outthis.timeFormat(outthis.audioCtx.duration);
      var currentTime = outthis.timeFormat(outthis.audioCtx.currentTime);
      console.log("播放回调方法调用"+duration+";currenttime"+currentTime)
      outthis.setData({
        'currentplay.currentTime':currentTime,
        'current.duration':duration
      })
    });
   
  },
  timeFormat:function(time){
    var minutes = Math.floor(time/60);
    var lminutes = ""
    if(minutes<10){
      lminutes = '0'+ minutes
    }else{
      lminutes = minutes
    }
    var seconds = Math.floor(time)%60;
    var lseconds = ""
    if(seconds<10){
      lseconds = '0'+ seconds
    }else{
      lseconds = seconds;
    }
    console.log(lminutes+":"+lseconds)
    return(lminutes+":"+lseconds);
  },
  setMusic:function(tempIndex){
    //当前播放歌曲的信息
     var currentMusic =  this.data.playlist[tempIndex];
     //设置音频播放的地址
     this.audioCtx.src = currentMusic.src;
     this.setData({
      playindex:tempIndex,
      'currentplay.id':currentMusic.id,
      'currentplay.title':currentMusic.title,
      'currentplay.singer':currentMusic.singer,
      'currentplay.coverImage':currentMusic.coverImage,
      'currentplay.src':currentMusic.src,
     });

  },


  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

pages/index/index1.wxss:

.tab{
  display: flex;
  flex-direction: row;
}
.tab-item{
  flex: 1;
  text-align: center;
  border-bottom: 6rpx solid #eee;
  font-size: 10pt;
  line-height: 72rpx;
  color: white;
}

.tab-item.active{
  border-bottom: 6rpx solid #c25b5b;
  color: #c25b5b;
}

page{
  background-color: #1a1818;
  display: flex;
  flex-direction: column;
  height: 100%;
  color: #ccc;
}
.content{
  flex: 1;
}
.content-info-portal{
  display: flex;
  flex-direction: row;
}

.content-info-portal image{
  width: 120rpx;
  height:120rpx;
}

/* 轮播图 */
.content-info-side{
  height: 150px;
}
.content-info-side image{
  width: 100%;
  height: 100%;
}
.content >swiper{
  height: 100%;
}
/* 功能按钮 */
.content-info-portal{
  display: flex;
  flex-direction: row;
  }
  .content-info-portal >view{
    flex: 1;
    font-size: 11pt;
    text-align: center;
  }
  
  .content-info-portal image{
    width: 120rpx;
    height: 120rpx;
    display: block;
    margin: 20rpx auto;
  }
  .list-inner{
    display: flex;
    flex-wrap: wrap;
    flex-direction: row;
  }
  .list-item{
    flex:1;
    margin: 15rpx;
    font-size: 10pt;
  }
  
  .list-item image{
    width: 200rpx;
    height: 200rpx;
    display: block;
    margin: 0 auto;
    border-radius: 10rpx;
    border: 1rpx solid #555;
  }
  /* 播放器部分 */
.player{
  height: 112rpx;
  display: flex;
  flex-direction: row;
  align-items: center;
  background: chocolate;
}
.player>image{
  width: 80rpx;
  height: 80rpx;
  margin-left: 15rpx;
  border-radius: 10rpx;
  border: 1px solid #333;
}

.player-control image{
  width: 80rpx;
  height: 80rpx;
}
.player-info{
  flex: 1;
  font-size: 10pt;
  line-height: 38rpx;
  margin-left: 20rpx;

}
.player-info-singer{
  color: #555;
}

/* 实现播放器的样式 */
.content-play{
  display: flex;
  flex-direction: column;
  height: 100%;
  text-align: center;
  justify-content: space-around;
}
.content-play-cover>image{
    width: 320rpx;
    height: 320rpx;
    border-radius: 50%;
    border: 1px solid #555;
    animation: roateImage 10s linear infinite;
}
@keyframes roateImage{
  from{
    transform: rotate(0deg);
  }
  to{
    transform: rotate(360deg);
  }
}

/* 播放进度条的样式 */
.content-play-progress{
  display: flex;
  text-align: center;
  margin: 0 35rpx;
  font-size: 10pt;
  align-items: center;
}
.content-play-progress>slider{
  flex: 1;
}
.playlist-content{
  display: flex;
  flex-direction: column;
  height: 100%;
}
.playlist-item{
display: flex;
height: 112rpx;
align-items: center;
border-bottom: 1px solid #555;
}
.playlist-item>image{
width: 80rpx;
height: 80rpx;
border-radius: 10rpx;
border: 1px solid #555;
margin-left: 15rpx;
}
.playlist-item-info{
  flex: 1;
  font-size: 10pt;
  line-height: 38rpx;
  margin-left: 20rpx;
  padding: 0 5rpx;
}
.playlist-item-play{
  font-size: 10pt;
  color: #c25b5b;
  margin-right: 20rpx;
}

pages/index/index1.wxml:

<view class="tab">
  <view class="tab-item {
   
   {item ==0?'active':'' }}" data-item="0" bindtap="changeItem">音乐推荐</view>
  <view class="tab-item {
   
   {item ==1?'active':'' }}" data-item="1" bindtap="changeItem">播放器</view>
  <view class="tab-item {
   
   {item ==2?'active':'' }}" data-item="2" bindtap="changeItem">播放列表</view>
</view>
<!-- 正文信息-->
<view class="content">
  <swiper current="{
   
   {item}}" bindchange="changeTab">
    <swiper-item>
      <include src="./info"></include>
    </swiper-item>
    <swiper-item>
      <include src="./play"></include>
    </swiper-item>
    <swiper-item>
      <include src="./playlist"></include>
    </swiper-item>
  </swiper>
</view>
<!-- 播放器-->
<view class="player">
  <image src="{
   
   {currentplay.coverImage}}" />
  <view class="player-info">
    <view>{
   
   {currentplay.title}}</view>
    <view class="player-info-singer">{
   
   {currentplay.singer}}</view>
  </view>
  <view class="player-control">
    <image src="../images/01.png" />
    <!-- 播放或暂停 -->
    <image wx:if="{
   
   {state=='paused'}}" src="../images/02.png" bindtap="play" />
    <image wx:if="{
   
   {state =='running'}}" src="../images/02stop.png" bindtap="pause" />
    <!-- 切换到下一首 -->
    <image src="../images/03.png" bindtap="next" />
  </view>
</view>

pages/index/info.wxml:

<swiper class="content-info-side" indicator-dots="true" indicator-color="#eee" indicator-active-color="#ffffff">
  <swiper-item>
    <image src="../images/banner.jpg" mode="aspectFill"></image>
  </swiper-item>
  <swiper-item>
    <image src="../images/banner.jpg" mode="aspectFill"></image>
  </swiper-item>
  <swiper-item>
    <image src="../images/banner.jpg" mode="aspectFill"></image>
  </swiper-item>
</swiper>
<!--功能按钮功能区域-->
<view class="content-info-portal">
  <view>
    <image src="../images/04.png"></image>
    <text>私人FM</text>
  </view>
  <view>
    <image src="../images/05.png"></image>
    <text>每日歌曲推荐</text>
  </view>
  <view>
    <image src="../images/06.png"></image>
    <text>云音乐新歌榜</text>
  </view>

</view>
<!--推荐歌曲区域-->
<view class="content-info-list">
  <text>推荐歌曲</text>
  <view class="list-inner">
    <view class="list-item">
      <image src="../images/cover.jpg"></image>
      <text>紫罗兰</text>
    </view>
    <view class="list-item">
      <image src="../images/cover.jpg"></image>
      <text>欢乐颂</text>
    </view>
    <view class="list-item">
      <image src="../images/cover.jpg"></image>
      <text>再见</text>
    </view>
    <view class="list-item">
      <image src="../images/cover.jpg"></image>
      <text>紫罗兰</text>
    </view>
    <view class="list-item">
      <image src="../images/cover.jpg"></image>
      <text>紫罗兰</text>
    </view>
    <view class="list-item">
      <image src="../images/cover.jpg"></image>
      <text>紫罗兰</text>
    </view>

  </view>

</view>

pages/index/play.wxml:

<view class="content-play">
  <!-- 显示播放信息 -->
  <view>
    <view>肖邦的夜曲</view>
    <view>--肖邦--</view>
  </view>
  <view class="content-play-cover">
    <image src="../images/cover.jpg" style="animation-play-state: {
   
   {state}};" />
  </view>
  <view class="content-play-progress">
    <text>{
   
   {currentplay.currentTime}}</text>
    <slider activeColor="#555" backgroundColor="#e9e9e9" block-size="12" block-color="#e9e9e9" value="80" bindchange="testBind" bindchanging="testBinding"></slider>
    <text>{
   
   {currentplay.duration}}</text>
  </view>
</view>

pages/index/playlist.wxml:

<view class="playlist-content">
  <label wx:for="{
   
   {playlist}}" wx:key="id">
    <view class="playlist-item" data-index="{
   
   {index}}" bindtap="changeMusic">
      <!-- <image src="../images/cover.jpg" /> -->
      <image src="{
   
   {item.coverImage}}"></image>
      <view class="playlist-item-info">
        <!-- <view>肖邦的夜曲</view> -->
        <view>{
   
   {item.title}}</view>
        <view>{
   
   {item.singer}}</view>
      </view>
      <view class="playlist-item-play" wx:if="{
   
   {index==playindex}}">
        正在播放
      </view>
    </view>
  </label>
</view>

Supongo que te gusta

Origin blog.csdn.net/RosalynZhuo/article/details/128355645
Recomendado
Clasificación