探索网易年度报告:一个独特的动画展示

833 阅读7分钟

效果展示

效果图

image.png

  • 在数字时代,呈现年度报告的方式已经变得多样化。然而,作为一个对创新充满激情的网易粉丝,呆同学决定采用一种与众不同的方式来展示自己的年度成就:通过动画。这个决定并不仅仅是为了追求视觉上的吸引力,更重要的是希望通过动态和互动性来呈现网易在过去一年里的辉煌成就。在这篇文章中,我将分享我的创作过程以及我是如何使用 CSS、HTML 和 JS 创造一个独特而引人注目的网易年度报告的。

技术选择

选择使用 CSS、HTML 和 JS 来制作动画。

HTML结构

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网易年度总结报告</title>
    <link rel="stylesheet" href="./index.css">
    <!-- icon 网站图标 -->
    <link rel="icon" href="https://s1.music.126.net/style/favicon.ico">
</head>

<body>
    <!-- 音频播放 -->
    <audio id="j-bgm" src="./assets/bgm.mp3"></audio>
    <!-- 音频关闭 -->
    <div class="music-btn off"></div>
    <div class="view">
        <div class="sun"></div>
        <!-- 秋千 -->
        <div class="art">
            <div class="swing">
                <div class="leg2">
                    <div class="jiojio"></div>
                </div>
                <div class="leg1">
                    <div class="jiojio"></div>
                </div>

                <!-- neck -->
                <div class="neck"></div>
                <!-- <head> -->
                <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. <audio> 元素定义了页面中的音频资源
  2. 定义一个类名为music-btn off用于存放音乐开关
  3. 定义一个类名为view的容器:
  • 在该容器内定义sun容器,用于存放背景中的太阳

  • 在该容器内定义art容器,在art容器中再定义swing容器,用于存放秋千和人,在swing容器中再定义leg2,neck,head,leg1分别用于存放腿2,脖子,头,腿1

  • 在leg2和leg1再定义jiojio容器,用于存放脚

  • 在head容器中再定义part容器,用于存放头发

  • 定义paras容器,用于存放文字,里面通过p和em标签元素来实现效果,设置style="transition-delay: xxxs;" 来实现文字慢慢出现的效果

CSS实现

* {
    margin: 0;
    padding: 0;
}
html, body {
    width: 100%;
    height: 100%;
}
.music-btn {
    position: fixed;
    top: 25px;
    left: 25px;
    width: 40px;
    height: 40px;
    background: url(./assets/close.png);
    /* 图片覆盖整个容器 */
    background-size: cover;
    /* 防止被后面的样式覆盖,提高优先级 */
    z-index: 3;
}
.music-btn.off {
    background-image: url(./assets/music.png);

}
.view {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
    /* 渐变 */
    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);
    background-size: cover;
    left: 50%;
    transform: translate(-50%, -50%);
}
.art {
    position: absolute;
    top: -140px;
    right: 0;
    width: 750px;
    height: 1334px;
    /* 缩放 */
    transform: scale(0.5);
    /* 旋转点 */
    transform-origin: top right;
}

.swing {
    position: absolute;
    left: 226px;
    top: -180px;
    width: 478px;
    height: 1038px;
    background-image: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/swing.88545d6c8e1ac798465e367f8e5357ab.png);
    transform-origin: -16% -30%;
    animation: ani_qiuqian 6s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
}
@keyframes ani_qiuqian {
    0% {
        transform: rotateZ(0deg);
    }
    50% {
        transform: rotateZ(32deg);
    }
    100% {
        transform: rotateZ(0deg);
    }
}

.leg2 {
    position: absolute;
    left: 185.375px;
    top: 958px;
    width: 130px;
    height: 32px;
    background-image: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg2.d7bc44a91b6974450f2ccc430846c63d.png);
    transform-origin: 91.15% 33.59%;
    animation: ani_leg2 8s ease infinite;
}
@keyframes ani_leg2 {
    0% {
        transform: rotateZ(0deg);
    }
    25% {
        transform: rotateZ(-87deg);
    }
    50% {
        transform: rotateZ(0deg);
    }
    75% {
        transform: rotateZ(-87deg);
    }
    100% {
        transform: rotateZ(0deg);
    }
}
.leg2 .jiojio {
    width: 57px;
    height: 44px;
    background-image: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg2-part.8f70bb7fc789a70bc78c48aa7718a765.png);
    left: -27.75px;
    top: -10.5px;
    position: absolute;
}

.leg1 {
    position: absolute;
    left: 290.375px;
    top: 955.25px;
    width: 63px;
    height: 130px;
    background-image: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg1.b1df6a7d1a794d36fbd0e1277733e1cf.png);
    transform-origin: 17.857% 13.365%;
    animation: ani_leg1 8s ease infinite;
}
@keyframes ani_leg1 {
    0% {
        transform: rotateZ(0deg);
    }
    25% {
        transform: rotateZ(109deg);
    }
    50% {
        transform: rotateZ(0deg);
    }
    75% {
        transform: rotateZ(109deg);
    }
    100% {
        transform: rotateZ(0deg);
    }
}
.leg1 .jiojio {
    width: 39px;
    height: 62px;
    background-image: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg1-part.f2f17703a6af8fd2af5e0f5a9f320623.png);
    left: 26.25px;
    top: 102.5px;
    position: absolute;
}
.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;
  }
  1. 全局样式重置:

    • 使用 * 选择器将所有元素的外边距和内边距重置为零,确保页面在不同浏览器上的一致性。
  2. 页面结构设置:

    • 设置 htmlbody 元素的宽度和高度为100%,使得页面占满整个浏览器窗口。
  3. 音乐按钮样式:

    • 设置音乐按钮的固定定位,使其始终位于页面的左上角。
    • 使用两种不同的背景图片(关闭状态和播放状态)来表示音乐按钮的状态变化。
    • 使用 z-index 属性确保音乐按钮始终在页面的顶部。
  4. 背景设置:

    • 使用线性渐变 linear-gradient 创建页面的背景色。
    • 渐变色范围从上到下逐渐变化,使得页面看起来更加生动。
  5. 太阳动画效果:

    • 使用绝对定位将太阳定位在页面的中间上方,并通过 transform: translate(-50%, -50%); 属性将其居中显示。
    • 使用背景图片来表示太阳,通过 background-size: cover; 属性确保图片覆盖整个容器。
  6. 秋千动画效果:

    • 使用绝对定位将秋千定位在页面的右上方,并通过 transform: scale(0.5); 属性将其缩小。
    • 使用背景图片来表示秋千,并通过 transform-origin: top right; 属性设置旋转的基点为右上角。
    • 使用 @keyframesanimation 属性定义秋千摆动的动画效果,并使其无限循环播放。
  7. 秋千上的人物部分动画效果:

    • 使用绝对定位将秋千上的人物部分定位在合适的位置。
    • 使用背景图片来表示人物的不同部分(腿、头、脖子等)。
    • 使用 @keyframesanimation 属性定义人物部分的摆动动画效果,并使其无限循环播放。
  8. 特殊内容动画效果:

    • 使用绝对定位将特殊内容定位在页面的合适位置。
    • 使用 @keyframestransition 属性定义特殊内容的进入动画效果,使其在页面加载时以渐显的方式出现。

JS控制

<script>
        //播放音乐
        var musicBtn = document.querySelector('.music-btn');
        var bgMusic = document.getElementById('j-bgm');
        var defaultMusicPlay = true;

        var viewSpecial = document.querySelector('.view .paras');

        musicBtn.addEventListener('click', function () {
            if (defaultMusicPlay) {
                bgMusic.play();
            } else {
                bgMusic.pause();
            }
            musicBtn.classList.toggle('off');
            defaultMusicPlay = !defaultMusicPlay;
        });

        setTimeout(() => {
            viewSpecial.classList.add('z-enter')
        }, 1000)
    </script>
  1. 获取元素:
  • 使用 document.querySelector('.music-btn') 获取页面中类名为 music-btn 的元素,即音乐按钮。 - 使用 document.getElementById('j-bgm') 获取页面中 ID 为 j-bgm 的元素,即音乐播放器。 - 使用 document.querySelector('.view .paras') 获取页面中 .view 下类名为 paras 的元素,用于特殊内容的动画效果。
  1. 事件监听:

    • 使用 addEventListener 方法监听音乐按钮的点击事件。
    • 当按钮被点击时,执行一个匿名函数,该函数控制音乐的播放和暂停。
  2. 音乐播放控制逻辑:

    • 如果 defaultMusicPlay 变量的值为 true,则调用 bgMusic.play() 方法播放音乐。
    • 否则,调用 bgMusic.pause() 方法暂停音乐。
    • 使用 classList.toggle('off') 方法切换音乐按钮的状态,如果按钮之前是关闭状态,则添加 off 类,显示播放音乐的图标;如果按钮之前是播放状态,则移除 off 类,显示关闭音乐的图标。
    • 最后,将 defaultMusicPlay 变量的值取反,以便下一次点击按钮时执行相反的操作。
  3. 特殊内容动画效果:

    • 使用 setTimeout 函数,在页面加载后延迟一秒钟执行。
    • 在延迟执行的函数中,给特殊内容添加 z-enter 类,触发特殊内容的进入动画效果。

总结

这个项目对我来说是一次挑战和成长的机会。通过使用 CSS、HTML 和 JavaScript,我成功地呈现了一个以网易风格为灵感的动画,作为网易年度报告的创意表达。我深入研究了每个细节,从太阳到秋千再到特殊内容的动画效果,力求将网易的品牌形象和视觉风格完美展现。这次经历不仅展示了我的技术能力,也让我更加了解了前端开发的艺术之美。