编织音符的时光:网易云音乐年终报告编写指南

228 阅读6分钟

前言

在年末岁末,我们不禁回首过去的一年,回忆起那些陪伴我们的音乐时光。网易云音乐作为国内领先的音乐平台,为我们提供了一个与音乐相伴的空间,记录下了我们生活中的点点滴滴。而网易云音乐年终报告,则是一个不可多得的机会,让我们以数据的方式回顾过去一年的音乐旅程,感受音乐带给我们的情感和记忆。

本文将带您深入探索如何编写网易云音乐年终报告,从开始到结束,逐步解析报告的构建过程,帮助您展现个性化的音乐年度总结。无论您是音乐爱好者、数据分析师还是文学艺术家,都能在这篇文章中找到编写网易云音乐年终报告的灵感和技巧。

让我们一起踏上这段音乐之旅,用文字和数据描绘属于我们自己的音乐年终篇章,为音乐留下珍贵的记忆,为未来播下无限的可能性。

效果预览

image.png

在预览效果中,您可以看到模拟年终报告的内容和结构。虽然这只是一个简单的示例,但它展示了如何来呈现网易云音乐年终报告的一部分内容。完整的报告将会结合更多的数据和文字来完整地呈现过去一年的音乐旅程。

代码展示

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可以引入很多种类型的文件,比如css、js、图片等等,这里我们引入了一个css文件 -->
    <link rel="icon" href="https://s1.music.126.net/style/favicon.ico">
    <!-- 引入图标 -->
    <link rel="stylesheet" href="./style.css">
</head>

<body>
    <!-- 媒体标签,用于播放音频 -->
    <audio id="j-bgm" src="./assets/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>
    <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;
            // 如果有这个类名off,则移除,没有则添加
            musicBtn.classList.toggle('off');
        });

        setTimeout(() => {
            viewSpecial.classList.add('z-enter')
        }, 1000)
    </script>
</body>

</html>

css部分

* {
    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(./assets/close.png)
    no-repeat center / cover;
    z-index: 999;
  }
  .music-btn.off {
    background-image: url(./assets/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%;
    /* aimation各个参数的作用: 1. 动画名称: ani3_swing 2. 持续时间: 8s 3. 缓动函数: ease 4. 重复次数: infinite */
    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;
  }
  

代码解析

  • <audio id="j-bgm" src="./assets/bgm.mp3"></audio>:音频标签,用于播放背景音乐。其中,id 属性为 "j-bgm",用于在 JavaScript 中引用该元素。
  • <div class="music-btn off"></div>:音乐按钮,用于控制音乐的播放。初始状态下,按钮带有 "off" 类,表示音乐处于关闭状态。
  • <div class="view special">...</div>:特殊的视图容器,用于展示音乐报告的内容。包含了太阳、秋千、文字等特殊效果的展示。
  • <div class="paras">...</div>:用于展示特殊内容的容器,其中包含了音乐报告的文字内容。
  • * {...}:通配符选择器,将所有元素的 marginpadding 设置为零,确保页面布局一致性。
  • html, body {...}:选择 HTML 和 body 元素,并将它们的宽度和高度设置为 100%,以使页面充满整个窗口。
  • document.querySelector('.view .paras'):通过 CSS 选择器获取特殊视图容器中的文字内容容器。
  • document.querySelector('.music-btn'):通过 CSS 选择器获取音乐按钮元素。
  • bgMusic.play():播放背景音乐。
  • bgMusic.pause():暂停背景音乐。
  • musicBtn.classList.toggle('off'):切换音乐按钮的状态,如果有 "off" 类,则移除,否则添加。
  • setTimeout(() => { ... }, 1000):在页面加载后延迟一秒钟,然后向特殊视图容器添加一个动画效果。

结语

在音乐的海洋里,我们编织了一幅幅五线谱的时光画卷。每一个音符都是我们生活中的一个瞬间,每一首歌都是我们情感的寄托。回顾过去一年,我们跟随着旋律的节拍,感受着悲欢离合。在音乐的陪伴下,我们经历了生活的起伏,度过了情感的浪潮。或许有悲伤,或许有欢笑,但每一段旋律都烙印在我们的心灵深处,成为了不可磨灭的记忆。让我们继续用音乐去书写我们的时光,用心去感受每一个音符,让美好的旋律永远伴随着我们,编织出更加绚丽多彩的未来。