Vue implementa el desplazamiento de letras

      Hace poco leí una publicación de blog sobre visualización de audio y accidentalmente pensé en el efecto del desplazamiento de letras. Aunque hay muchos artículos en Internet que presentan el desplazamiento de letras, no todos tienen la misma idea, así que me gustaría compartir con ustedes algunas de mis propias ideas y cómo lograr esta función.

    Idea: Obtenga los datos de las letras de LRC que coincidan con las  letras de desplazamiento de LRC de Netease Cloud Music , obtenga el tiempo de reproducción en tiempo real del audio, haga coincidir el texto correspondiente con el tiempo de las letras de LRC, agregue animación al texto de letras actual a través del control js y modifique el tiempo de ejecución de la animación.

1. Procesamiento de datos de letras

    Los datos de letras originales en realidad no necesitan que los generemos, en realidad es una cadena de cadenas con tiempo y letras, primero debe convertirse en un objeto de matriz para facilitar su uso.

   Utilice Netease Cloud LRC para desplazarse por las letras y obtener las letras que desee. Para conocer el método específico, consulte el enlace anterior.

Primero declare la función formatLrc para procesar los datos originales, intercepte la cadena a través de la división, elimine el carácter de nueva línea u obtenga una nueva matriz, repita la nueva matriz e intercepte de acuerdo con ']', el nuevo formato de matriz es similar a ['[01:42.000', 'sin usted'] Obviamente hay más símbolos '[', use el método substring() para interceptar cada '[', y guarde todos los datos procesados, que es el formato de datos que queremos. El código específico es el siguiente:

 formatLrc() {
      var strLrc = this.LRC.split("\n");//按换行截取字符串,去掉换行得到一个数组strLrc 
      let arr=[]//声明数组
      for (var i = 0; i < strLrc.length; i++) {//循环strLrc 
        var str = strLrc[i];
        var parts = str.split("]");//按照']'截取strLrc的每一项,得到新数组parts 
        var timeStr = parts[0].substring(1);//获取时间字符串
        var obj = {
          time: timeStr,
          words: parts[1],
        };
        arr.push(obj)//每循环一次把obj添加到arr数组末尾
      }
      return arr;
    },

  A través del procesamiento anterior, se obtienen nuevos datos.El formato específico de los datos es el siguiente:

 2. Obtenga el tiempo de reproducción actual 

 <audio :src="music" @timeupdate="audioTime" controls></audio>

El control de reproducción de audio tiene un evento @timeupdate que puede retroalimentar la información de progreso de reproducción actual en tiempo real y encapsular la función audioTime.El código específico es el siguiente:

  audioTime(e) {
      var time = e.target.currentTime; //当前播放器时间
      for (var i = 0; i < this.lrcData.length; i++) {
        if (time < this.lrcData[i].time) {
          //循环歌词数组,当播放器当前时间第一次小于歌词时间时当前数组下标减一即为当前时间数组所对应歌词下标
          this.dataWords = this.lrcData[i - 1].words;
          //保存当前歌词动画执行事件
          this.lrcTime = this.lrcData[i].time - this.lrcData[i - 1].time;
          return i - 1;
        }
      }
    },

    Después de obtener el tiempo de reproducción actual, coincide con el tiempo en la matriz de letras. Cuando el tiempo actual del reproductor es menor que el tiempo de las letras por primera vez, el subíndice de la matriz actual menos uno es el subíndice de las letras correspondientes a la matriz de tiempo actual.

El diseño de página específico que escribí aquí es relativamente simple, principalmente solo hay un control de reproducción

<template>
  <div>
    <audio :src="music" @timeupdate="audioTime" controls></audio>
    <div
      :class="className"
      :style="{ 'animation-duration': `${lrcTime}000ms` }" >
      {
   
   { dataWords }}
    </div>
  </div>
</template>

 CSS define la animación para realizar el cambio lento de color de la letra de izquierda a derecha.

@keyframes scan {
  0% {
    background-size: 0 100%;
  }
  100% {
    background-size: 100% 100%;
  }
}
.text {
  background: #7e7e7e -webkit-linear-gradient(left, #76ca16, #0fa046) no-repeat 0
    0;
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  background-size: 0 100%;
}
.load {
  background-size: 100% 100%;
  animation: scan linear;
}

    Dado que el tiempo de canto de cada letra es diferente, si el tiempo de ejecución de cada animación de letra es el mismo, la página será muy rígida e incómoda. Utilicé un método estúpido aquí, restando el tiempo de la letra actual del tiempo de la siguiente letra, y el resultado es el tiempo requerido para cantar la letra actual, y cambiando el tiempo de animación de la letra al tiempo adquirido actualmente, se puede realizar el efecto de sincronizar la letra y el tiempo de canto. El código específico es el siguiente:

 audioTime(e) {
      var time = e.target.currentTime; //当前播放器时间
      for (var i = 0; i < this.lrcData.length; i++) {
        if (time < this.lrcData[i].time) {
          //循环歌词数组,当播放器当前时间第一次小于歌词时间时当前数组下标减一即为当前时间数组所对应歌词下标
          this.lrcTime = this.lrcData[i].time - this.lrcData[i - 1].time;
          this.dataWords = this.lrcData[i - 1].words;
          return i - 1;
        }
      }
    },

En resumen, puede obtener un desplazamiento de letras simple con efecto de sincronización de canciones.

Aquí está el código completo:

<template>
  <div class="hello">
    <audio :src="music" @timeupdate="audioTime" controls></audio>
    <div
      :class="className"
      :style="{ 'animation-duration': `${lrcTime}000ms` }" >
      {
   
   { dataWords }}
    </div>
  </div>
</template>

<script>
import music from "../assets/music.mp3";
export default {
  data() {
    return {
      className: "text load",
      lrcTime: "",
      music,
      currenttime: "",
      LRC: `[00:00.000] 作词 : 周耀辉/李焯雄
[00:01.000] 作曲 : 林健华
[00:02.000] 编曲 : 林健华
[00:15.000]忽然之间
[00:18.000]天昏地暗
[00:21.000]世界可以忽然什么都没有
[00:28.000]我想起了你
[00:32.000]再想到自己
[00:35.000]我为什么总在非常脆弱的时候
[00:40.000]怀念你
[00:43.000]''
[00:44.000]我明白太放不开你的爱
[00:49.000]太熟悉你的关怀分不开
[00:54.000]想你算是安慰还是悲哀
[00:58.000]而现在就算时针都停摆
[01:03.000]就算生命像尘埃分不开
[01:08.000]我们也许反而更相信爱
[01:24.000]''
[01:25.000]如果这天地
[01:29.000]最终会消失
[01:32.000]不想一路走来珍惜的回忆
[01:38.000]没有你
[01:40.000]''
[01:41.000]我明白太放不开你的爱
[01:46.000]太熟悉你的关怀分不开
[01:51.000]想你算是安慰还是悲哀
[01:55.000]而现在就算时针都停摆
[02:00.000]就算生命像尘埃分不开
[02:05.000]我们也许反而更相信爱
[02:34.000]''
[02:35.000]我明白太放不开你的爱
[02:40.000]太熟悉你的关怀分不开
[02:45.000]想你算是安慰还是悲哀
[02:49.000]而现在就算时针都停摆
[02:54.000]就算生命像尘埃分不开
[03:00.000]我们也许反而更相信爱`,
      lrcData: "",
      dataWords: "",
    };
  },
  name: "HelloWorld",
  methods: {
    //歌词数据转化为数组
    formatLrc() {
      var strLrc = this.LRC.split("\n");
      let arr = [];
      for (var i = 0; i < strLrc.length; i++) {
        var str = strLrc[i];
        var parts = str.split("]");
        var timeStr = parts[0].substring(1);
        var obj = {
          time: this.formatTime(timeStr),
          words: parts[1],
        };
        arr.push(obj);
      }
      this.lrcData = arr;
    },
    //时间转换(秒)
    formatTime(time) {
      var parts = time.split(":"); //[03:00.000]==>[03,00.00]
      return +parts[0] * 60 + +parts[1]; //计算秒
    },
    audioTime(e) {
      var time = e.target.currentTime; //当前播放器时间
      for (var i = 0; i < this.lrcData.length; i++) {
        if (time < this.lrcData[i].time) {
          //循环歌词数组,当播放器当前时间第一次小于歌词时间时当前数组下标减一即为当前时间数组所对应歌词下标
          this.lrcTime = this.lrcData[i].time - this.lrcData[i - 1].time;
          this.dataWords = this.lrcData[i - 1].words;
          return i - 1;
        }
      }
    },
  },
  watch: {
    dataWords() {
      this.className = "text";
      setTimeout(() => {
        this.className = "text load";
      }, 50);
    },
  },
  mounted() {
    this.formatLrc();
  },
};
</script> 
<style scoped>
@keyframes scan {
  0% {
    background-size: 0 100%;
  }
  100% {
    background-size: 100% 100%;
  }
}
.text {
  background: #7e7e7e -webkit-linear-gradient(left, #76ca16, #0fa046) no-repeat 0
    0;
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  background-size: 0 100%;
}
.load {
  background-size: 100% 100%;
  animation: scan linear;
}
</style>

      El código es muy simple. La idea general y el código están aquí. Puede consultarlo. Todavía hay muchos detalles que deben optimizarse, como el cambio de animación y la velocidad de ejecución de cada tiempo de ejecución de animación. Puede continuar optimizando. ¡Aquí está solo para su referencia! ! También espero que me puedas dar más consejos y dejar un mensaje.

Supongo que te gusta

Origin blog.csdn.net/2303_76218115/article/details/129657440
Recomendado
Clasificación