掘金 后端 ( ) • 2024-04-24 10:15

theme: mk-cute

效果图

jcode

image.png

image.png

准备

close.png

close.png

music.png

music.png

自行找一个音频,文件摆放位置如下

image.png

代码和分析

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="icon" href="https://s1.music.126.net/style/favicon.ico">
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <audio src="./assets/bgm.mp3" id="j-bgm"></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>
                
                <!-- neck -->
                <div class="neck"></div>
                <!-- head -->
                <div class="head">
                    <div class="part"></div>
                </div>

                <div class="leg1">
                    <div class="jiojio"></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>
</html>

分析

  • 定义一个audio标签元素用于存放音频
  • 定义一个类名为music-btn off用于存放音乐开关
  • 定义一个类名为view的容器:
  1. 在该容器内定义sun容器,用于存放背景中的太阳
  2. 在该容器内定义art容器,在art容器中再定义swing容器,用于存放秋千和人,在swing容器中再定义leg2,neck,head,leg1分别用于存放腿2,脖子,头,腿1
  3. 在leg2和leg1再定义jiojio容器,用于存放脚
  4. 在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%;
    left: 50%; 
    width: 283px;
    height: 283px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/sun.a3f575ae2fef2cfdae15011e6081a094.png);
    background-size: cover;
    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: 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: 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{
    position: absolute;
    width: 57px;
    height: 44px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg2-part.8f70bb7fc789a70bc78c48aa7718a765.png);
    left: -27.75px;
    top: -10.5px;
}

.leg1{
    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);
    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{
    position: absolute;
    width: 39px;
    height: 62px;
    background: url(https://s5.music.126.net/static_public/5c21db8d4684556c72180904/leg1-part.f2f17703a6af8fd2af5e0f5a9f320623.png);
    left: 26.25px;
    top: 102.5px;
}
.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;
  }

分析

  • 秋千动画部分实现是通过@keyframes来实现,设置分别在0%,50%,100%时绕Z轴旋转的角度:

@keyframes ani_qiuqian{
    0% {
        transform: rotateZ(0deg);
    }
    50% {
        transform: rotateZ(32deg);
    }
    100% {
        transform: rotateZ(0deg);
    }
}

然后在秋千swing的css中通过animation来实现:

    animation: ani_qiuqian 6s cubic-bezier(0.455,0.03,0.515,0.955) infinite;
  • leg2leg1head也是同样的操作 js
 //播放音乐
        var viewSpecial = document.querySelector('.view .paras');
        var musicBtn = document.querySelector('.music-btn');
        var bgMusic = document.getElementById('j-bgm');
        var defaultMusicPlay = true;

        musicBtn.addEventListener('click' , function() {
           if ( defaultMusicPlay ){
            bgMusic.play();
            // musicBtn.classList.remove('off');
           } else {
            bgMusic.pause();
            // musicBtn.classList.add('off');
           }
           musicBtn.classList.toggle('off');//如果有自动移除;如果没有自动添加

           defaultMusicPlay = !defaultMusicPlay;
        })
        setTimeout(() => {
      viewSpecial.classList.add('z-enter')
    }, 1000)

分析

  • 通过document.querySelector('xxx') 来获取viewSpecial(文字容器),musicBtn容器(音乐按钮容器)
  • 通过document.getElementById('xxx') 来获取bgMusic容器(音乐容器)
  • 定义defaultMusicPlay = true来实现音乐开关和图标切换
  • musicBtn绑定一个监听事件addEventListener,当点击的时候触发回调函数,如果defaultMusicPlaytrue音乐播放并且显示close.png,如果为false,则关闭音乐并显示music.png,以下代码可以实现音乐的开关和图片的切换
defaultMusicPlay = !defaultMusicPlay;
  • 下面代码可以实现如果有'off'自动移除;如果没有自动添加
musicBtn.classList.toggle('off');

最后

如果有收获的话,可以给小编点个赞鼓励鼓励嘛,有错误的话希望可以提出,我一定虚心请教,继续努力,带来更优质的文章!

image.png