theme: mk-cute
效果图
准备
close.png
music.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的容器:
- 在该容器内定义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%;
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;
- leg2和leg1,head也是同样的操作 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,当点击的时候触发回调函数,如果defaultMusicPlay为true则音乐播放并且显示close.png,如果为false,则关闭音乐并显示music.png,以下代码可以实现音乐的开关和图片的切换
defaultMusicPlay = !defaultMusicPlay;
- 下面代码可以实现如果有'off'自动移除;如果没有自动添加
musicBtn.classList.toggle('off');
最后
如果有收获的话,可以给小编点个赞鼓励鼓励嘛,有错误的话希望可以提出,我一定虚心请教,继续努力,带来更优质的文章!
相关内容