叮!你的网易云年度听歌报告来了

454 阅读8分钟

前言

在过去的一年里,我们通过网易云音乐体验了无数的旋律和节奏,它们陪伴我们度过了不同的时刻。如今,随着年度听歌报告的发布,我们有机会以一种全新的方式——通过JavaScript——来回顾这段音乐旅程。在这篇文章中,我们将探索如何利用JavaScript的强大功能来捕捉和呈现我们的音乐足迹,从而创建一个个性化且互动性强的年度听歌报告。我们将从数据的获取和处理开始,逐步深入到可视化的实现,最终展示一个既美观又富有信息量的报告。让我们开始这段代码与音符交织的旅程吧。

正文

  • 我们在实现这个动态效果时,先思考一下这个动画中具有哪些元素呢

  • 首先我们看html片段,用于展示一个年度听歌报告页面的基本结构和样式
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>年度听歌报告</title>
  <link rel="icon" href="https://s1.music.126.net/style/favicon.ico">
  <link rel="stylesheet" href="./index.css">
</head>

<body>
  <audio id="j-bgm" src="./assert/bgm.mp3"></audio>
  <div class="music-btn off"></div>

  <div class="view special">
    <div class="sun"></div>
    <!-- 荡秋千 -->
    <div class="art">
      <div class="swing j-anim03 z-anim">
        <!-- 腿 -->
        <div class="leg2">
          <div class="jiojio"></div>
        </div>
        <!-- 腿 -->
        <div class="leg1">
          <div class="jiojio"></div>
        </div>
        <!-- 脖子 -->
        <div class="neck"></div>
        <!-- 头 -->
        <div class="head">
          <div class="part"></div>
        </div>
      </div>
    </div>
    <!-- 特殊内容 -->
    <div class="paras">
      <p class="para f-animLineUp" style="transition-delay: 0.2s;">
        <em class="s-fcRed">11月11日</em>
      </p>
      <p class="para f-animLineUp" style="transition-delay: 0.3s;">
        大概是很特别的一天
      </p>
      <p class="para f-animLineUp" style="transition-delay: 0.4s;">
        这一天里
      </p>
      <p class="para f-animLineUp" style="transition-delay: 0.5s;">
        你把郑源的
        <em class="s-fcRed">《被伤过的心还可以爱谁》</em>
      </p>
      <p class="para f-animLineUp" style="transition-delay: 0.6s;">
        反复听了
        <em class="s-fcRed">10次</em>
      </p>
    </div>
  </div>
  
</body>

</html>
    
  1. <!DOCTYPE html>:声明文档类型为HTML5。

  2. <html lang="en">:HTML文档的根元素,指定了语言为英文。

  3. <head>:文档的头部,包含了一些元数据和引用的外部资源。

    • meta标签包含了字符编码、视口设置以及IE兼容性设置。
    • title标签定义了页面的标题。
    • link标签用于引入外部资源,这里引入了一个图标文件和一个样式表。
  4. <body>:文档的主体部分,包含了页面的实际内容。

    • <audio>元素定义了一个音频播放器,指定了音频文件的路径。
    • <div>元素包含了一个音乐按钮,初始状态为关闭。
    • <div>元素包含了一个特殊视图,展示了一个动画和一些特殊内容。
  5. 特殊视图包含了以下元素:

    • <div class="art">:用于绘制动画的容器。
    • 动画部分包含了一个人在荡秋千,通过DIV和CSS样式来实现。
    • <div class="paras">:包含了一些特殊内容的容器,其中有几个段落标签,展示了一些特殊日期和听歌行为。

整体来说,这段代码是一个简单的HTML页面,主要用于展示一个年度听歌报告,通过HTML和CSS来实现一些动画效果和特殊内容的展示。

  • 在html完成一个年度听歌报告页面的基本结构和样式我们该如何使用CSS和js来实现动画效果呢?
    * {
    margin: 0;
    padding: 0;
  }
  html, body {
    width: 100%;
    height: 100%;
  }
  /* music 按钮 */
  .music-btn {
    top: 25px;
    left: 25px;
    z-index: 3;
    position: fixed;
    width: 40px;height: 40px;
    background: url(./assert/close.png)
    no-repeat center / cover;
  }
  .music-btn.off {
    background-image: url(./assert/music.png);
  }
  .view {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
  /* 第二屏 特殊 view special*/
  .view.special {
    position: absolute;
    background-image: 
    linear-gradient(60deg,#f8ddd1,#faece5 73%,#fad2c0);
  }
  /* 中间太阳 */
  .sun {
    position: absolute;
    top: 45%;
    width: 283px;
    height: 283px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/sun.a3f575ae2fef2cfdae15011e6081a094.png) no-repeat;
    background-size: 100%;
    left: 50%;
    transform: translate(-50%,-50%);
  }
  /* 秋千 外层压缩 */
  .art {
    transform: scale(.5);
    position: absolute;
    top: -140px;
    right: 0;
    width: 750px;
    height: 1334px;
    transform: scale(.5);
    transform-origin: top right;
  }
  /* 秋千动画 */
  .swing {
    display: block;
    position: absolute;
    left: 226px;
    top: -180.25px;
    width: 478px;
    height: 1038px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/swing.88545d6c8e1ac798465e367f8e5357ab.png) no-repeat;
    transform-origin: -16.10878661% -29.76878613%;
    animation: ani4_qiuqian 6s cubic-bezier(.455,.03,.515,.955) infinite;
  }
  @keyframes ani4_qiuqian {
    0% {
      transform: rotateZ(0deg);
  }
  50% {
      transform: rotateZ(31.99359208deg);
  }
  100% {
      transform: rotateZ(0deg);
  }
  }
  /* 腿动画 */
  .swing .leg2 {
    display: block;
    position: absolute;
    left: 185.375px;
    top: 958px;
    width: 130px;
    height: 32px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg2.d7bc44a91b6974450f2ccc430846c63d.png) no-repeat;
    transform-origin: 91.1538461538462% 33.59375%;
    animation: ani7_leg2 8s ease infinite;
  }
  @keyframes ani7_leg2 {
    0% {
      transform: rotate(0deg);
  }
  25% {
      transform: rotate(-86.98199658deg);
  }
  50% {
      transform: rotate(0deg);
  }
  75% {
      transform: rotate(-86.98199658deg);
  }
  100% {
      transform: rotate(0deg);
  }
  }
  .swing .leg2 .jiojio {
    display: block;
    position: absolute;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg2-part.8f70bb7fc789a70bc78c48aa7718a765.png) no-repeat;
    left: -27.75px;
    top: -10.5px;
    width: 57px;
    height: 44px;
  }
  .swing .leg1 {
    display: block;
    position: absolute;
    left: 290.375px;
    top: 955.25px;
    width: 63px;
    height: 130px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg1.b1df6a7d1a794d36fbd0e1277733e1cf.png) no-repeat;
    transform-origin: 17.8571428571429% 13.3653846153846%;
    animation: ani5_leg1 8s ease infinite;
  }
  @keyframes ani5_leg1 {
    0% {
      transform: rotate(0deg);
  }
  25% {
      transform: rotate(108.97744399deg);
  }
  50% {
      transform: rotate(0deg);
  }
  75% {
      transform: rotate(108.97744399deg);
  }
  100% {
      transform: rotate(0deg);
  }
  }
  /* 腿的一部分 */
  .leg1 .jiojio {
    display: block;
    position: absolute;
    left: 26.25px;
    top: 102.5px;
    width: 39px;
    height: 62px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg1-part.f2f17703a6af8fd2af5e0f5a9f320623.png) no-repeat;
  }
  .swing .neck {
    position: absolute;
    left: 451.125px;
    top: 855.5px;
    width: 51px;
    height: 42px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/neck.07a0013beff9796ed79c2cea542e5af2.png) no-repeat;
  }
  /* 头 */
  .swing .neck, .swing .head {
    display: block;
    position: absolute;
    left: 451.125px;
    top: 855.5px;
    width: 51px;
    height: 42px;
  }
  /* 脖子 */
  .swing .neck {
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/neck.07a0013beff9796ed79c2cea542e5af2.png) no-repeat;
  }
  /* 头 */
  .swing .head {
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/head.90bf892023d7df0522a4b53fc07e38df.png) no-repeat;
    animation: ani2_head 8s ease infinite;
  }
  /* 头发 */
  .swing .head .part {
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/head-part.22d4381c4bd6cb1c3afd2b1bfcfe22f1.png) no-repeat;
    left: 20px;
    top: 2px;
    width: 40px;
    height: 47px;
    position: absolute;
  }
  @keyframes ani2_head {
    0% {
      transform: rotate(0deg);
  }
  25% {
      transform: rotate(-55deg);
  }
  62.5% {
      transform: rotate(-55deg);
  }
  87.92% {
      transform: rotate(0deg);
  }
  100% {
      transform: rotate(0deg);
  }
  }
  /* 特殊的内容 */
  .paras {
    bottom: 110px;
    left: 10.67%;
    position: absolute;
    line-height: 1.6667;
    letter-spacing: 1px;
    color: #333;
  }
  .s-fcRed {
    color: #df493a;
  }
  .z-enter .f-animLineUp {
    opacity: 1;
    transform: translateY(0);
    transition: opacity 1.2s,transform 1s;
  }
  .f-animLineUp {
    opacity: 0;
    transform: translateY(6px);
  }
  em, i {
    font-style: normal;
    text-align: left;
  }
  
  

这段CSS代码定义了页面的样式和动画效果:

  1. * { margin: 0; padding: 0; }: 这段CSS代码将所有元素的外边距和内边距都设置为0,以确保页面在不同浏览器中具有一致的外观。
  2. html, body { width: 100%; height: 100%; }: 这段CSS代码将HTML和body元素的宽度和高度设置为100%,以确保页面占据整个浏览器窗口的空间。
  3. .music-btn: 定义了音乐按钮的样式,包括位置、大小和背景图片。
  4. .music-btn.off: 当音乐按钮处于关闭状态时,修改了背景图片。
  5. .view.view.special: 定义了页面视图的样式,包括尺寸和溢出隐藏。
  6. .sun: 定义了太阳的样式,包括位置、大小和背景图片。
  7. .art: 定义了秋千的样式,包括位置、大小和背景图片。
  8. .swing: 定义了秋千的动画效果,包括位置、大小、背景图片和动画属性。
  9. .swing .leg2.swing .leg1: 定义了秋千的腿部动画效果,包括位置、大小、背景图片和动画属性。
  10. .swing .neck.swing .head: 定义了秋千的脖子和头部的样式,包括位置和大小。
  11. .swing .head .part: 定义了头部的部分(头发)的样式,包括位置、大小和背景图片。
  12. .paras: 定义了特殊内容的样式,包括位置、行高、字母间距和颜色。
  13. .s-fcRed: 定义了红色文字的颜色。
  14. .z-enter .f-animLineUp.f-animLineUp: 定义了一种动画效果,当元素进入视图时,其透明度和垂直方向的位移会发生变化。
  15. em, i: 定义了斜体文本的样式。

这些CSS代码一起定义了页面的布局、样式和动画效果,使得页面具有吸引人的外观和交互性。

  • 最后我们来展示一下js部分
    <script>
    const viewSpecial = document.querySelector('.view .paras');
    const musicBtn = document.querySelector('.music-btn');
    let defaultMusicPlay = true;
    const bgMusic = document.querySelector('#j-bgm');

    musicBtn.addEventListener('click', () => {
      if (defaultMusicPlay) {
        bgMusic.play();
      } else {
        bgMusic.pause();
      }
      defaultMusicPlay = !defaultMusicPlay;
      musicBtn.classList.toggle('off');
    });      
  
    setTimeout(() => {
      viewSpecial.classList.add('z-enter')
    }, 1000)
  </script>

这段JavaScript代码添加了一些交互功能到页面中:

  1. const viewSpecial = document.querySelector('.view .paras');: 这行代码选中了页面中的特殊内容容器。
  2. const musicBtn = document.querySelector('.music-btn');: 这行代码选中了页面中的音乐按钮。
  3. let defaultMusicPlay = true;: 这行代码定义了一个变量 defaultMusicPlay,用来追踪音乐播放状态,默认为 true,表示音乐播放中。
  4. const bgMusic = document.querySelector('#j-bgm');: 这行代码选中了页面中的背景音乐元素。
  5. musicBtn.addEventListener('click', () => { ... });: 这段代码添加了一个点击事件监听器,当音乐按钮被点击时执行相应的操作。
  6. 在点击事件处理函数中,根据当前音乐播放状态,切换音乐的播放和暂停,并更新音乐按钮的样式。
  7. setTimeout(() => { viewSpecial.classList.add('z-enter') }, 1000): 这段代码设置了一个定时器,在一秒后给特殊内容容器添加一个 z-enter 类,触发特殊内容的进入动画效果。

这些JavaScript代码增加了音乐播放控制功能和特殊内容的进入动画效果,使得页面更具交互性和吸引力。

结尾

在这篇文章中,我们通过使用 JavaScript 实现了一个简单的网易云音乐年度听歌报告页面。通过 HTML、CSS 和 JavaScript 的组合,我们展示了如何创建一个具有动态效果和交互功能的页面,让用户可以点击按钮控制音乐的播放和暂停,并观看到特殊内容的进入动画。这个项目不仅仅是一个技术实践,更是一个展示了如何利用前端技术创造出有趣、吸引人的网页体验的例子。希望本文能够对你了解如何利用 JavaScript 实现网易云音乐年度听歌报告有所帮助。如果你有任何问题或建议,欢迎在下方留言,谢谢阅读!