实现上面那种动画无缝转场,今天刷B站的时候发现的,感觉这种的动画好炫酷,而且实现起来也并不复杂,于是自己手写了一份(虽然写的很烂,但还是辛苦我了)
大致原理
通过观察地址栏,可以发现这种动画其实就是点击跳转链接的时候并不是立即跳转,而是等待动画结束的时候再跳转,其次,当进入新页面的时候先保留住动画,再按相反的方向执行这个动画就OK了。
所以大概流程就是:
- 点击链接 -> 定时器动画 ->跳转
- 当页面加载时->触发动画 -> 正常展示页面即可
这种效果按理按说应该做成一种通用型的结构,但是我只是做着玩玩,所以怎么简单怎么来了
对于页面结构,动画需要铺满整个屏幕,可以分成5个部分(自己定义,改改CSS样式就行),每个部分分成上下两条,每一个部分的动画都是同步的
第一个文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home | index</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.title {
display: flex;
position: relative;
width: 100%;
justify-content: space-between;
}
.left {
color: black;
font-weight: 700;
margin-left: 40px;
margin-top: 20px;
}
.right {
margin-right: 40px;
margin-top: 20px;
}
ul {
list-style: none;
display: flex;
width: 200px;
justify-content: space-around;
color: black;
font-weight: 700;
}
.text {
font-size: 200px;
text-align: center;
transform: translateY(50%);
top: -50%;
}
.animation {
position: fixed;
z-index: 1;
width: 100%;
height: 100%;
/* display: none; */
/* opacity: 0; */
}
.animation-ul {
width: 100%;
height: 100%;
}
.animation-ul li {
width: 20%;
height: 100%;
/* border: 1px solid black; */
}
.top,
.bottom {
width: 100%;
height: 50%;
background-color: #746CF2;
transition: all 1.5s ease;
/* border: 1px solid black; */
}
.top {
transform: translateY(0);
}
.bottom {
transform: translateY(0);
}
#Home {
cursor: pointer;
cursor: pointer;
}
</style>
</head>
<body>
<!-- #746CF2 -->
<div class="animation">
<ul class="animation-ul">
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
</ul>
</div>
<div class="title">
<div class="left">
WangKaiFu
</div>
<div class="right">
<ul>
<li id="about">Home</li>
<li id="Home">About</li>
<li>Contact</li>
</ul>
</div>
</div>
<div class="text">
INDEX
</div>
<script>
window.onload = function () {
const list = document.querySelectorAll(".animation-ul li");
setTimeout(() => {
for (let i = 0; i < list.length; i++) {
setTimeout(() => {
list[i].querySelector(".top").style.transform = "translateY(-100%)";
list[i].querySelector(".bottom").style.transform = "translateY(100%)";
console.log(list[i].querySelector(".top"))
}, 200 * i)
}
}, 0)
setTimeout(() => {
document.querySelector(".animation").style.display = "none";
}, 2100)
}
let home = document.querySelector("#Home");
const list = document.querySelectorAll(".animation-ul li");
console.log(list)
home.addEventListener("click", () => {
document.querySelector(".animation").style.display = "block";
setTimeout(() => {
setTimeout(() => {
location.href = "./about.html"
}, 2000)
for (let i = 0; i < list.length; i++) {
setTimeout(() => {
list[i].querySelector(".top").style.transform = "translateY(0)";
list[i].querySelector(".bottom").style.transform = "translateY(0)";
console.log(list[i].querySelector(".top"))
}, 200 * i)
}
}, 0)
})
</script>
</body>
</html>
第二个文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home | About</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.title {
display: flex;
position: relative;
width: 100%;
justify-content: space-between;
}
.left {
color: black;
font-weight: 700;
margin-left: 40px;
margin-top: 20px;
}
.right {
margin-right: 40px;
margin-top: 20px;
}
ul {
list-style: none;
display: flex;
width: 200px;
justify-content: space-around;
color: black;
font-weight: 700;
}
.text {
font-size: 200px;
text-align: center;
transform: translateY(50%);
top: -50%;
}
.animation {
position: fixed;
z-index: 1;
width: 100%;
height: 100%;
/* display: none; */
/* opacity: 0; */
}
.animation-ul {
width: 100%;
height: 100%;
}
.animation-ul li {
width: 20%;
height: 100%;
/* border: 1px solid black; */
}
.top,
.bottom {
width: 100%;
height: 50%;
background-color: #746CF2;
transition: all 1.5s ease;
/* border: 1px solid black; */
}
.top {
transform: translateY(0);
}
.bottom {
transform: translateY(0);
}
#Home {
cursor: pointer;
cursor: pointer;
}
</style>
</head>
<body>
<!-- #746CF2 -->
<div class="animation">
<ul class="animation-ul">
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
<li>
<div class="top"></div>
<div class="bottom"></div>
</li>
</ul>
</div>
<div class="title">
<div class="left">
WangKaiFu
</div>
<div class="right">
<ul>
<li id="Home">Home</li>
<li id="About">About</li>
<li>Contact</li>
</ul>
</div>
</div>
<div class="text">
About
</div>
<script>
window.onload = function () {
const list = document.querySelectorAll(".animation-ul li");
setTimeout(() => {
for (let i = 0; i < list.length; i++) {
setTimeout(() => {
list[i].querySelector(".top").style.transform = "translateY(-100%)";
list[i].querySelector(".bottom").style.transform = "translateY(100%)";
console.log(list[i].querySelector(".top"))
}, 200 * i)
}
}, 0)
setTimeout(() => {
document.querySelector(".animation").style.display = "none";
}, 2200)
}
let home = document.querySelector("#Home");
const list = document.querySelectorAll(".animation-ul li");
console.log(list)
home.addEventListener("click", () => {
document.querySelector(".animation").style.display = "block";
setTimeout(() => {
setTimeout(() => {
location.href = "./index.html"
}, 2000)
for (let i = 0; i < list.length; i++) {
setTimeout(() => {
list[i].querySelector(".top").style.transform = "translateY(0)";
list[i].querySelector(".bottom").style.transform = "translateY(0)";
console.log(list[i].querySelector(".top"))
}, 200 * i)
}
}, 0)
})
</script>
</body>
</html>
在做动画的时候遇到了什么问题呢?
第一个,最开始的时候需要将整个动画div隐藏(display:none),当点击按钮的时候再显示,并执行动画,通过JS可以很轻松实现,但是观察效果的时候发现整个动画完全不见了,这可能是js有类似重排序指令?或者同步执行代码过快,当动画已经开始位移的时候页面还是隐藏状态,然后突然想起来了setTimeout(0)这个感觉没啥用的定时器,因为js会先执行同步代码,然后再执行异步代码,隐藏将动画放入到setTimeout(0)就完美解决了顺序问题(看来面试题还是有用的)
第二个,还是定时器的问题,因为要控制每一个动画div的分开移动,我在for遍历的时候再每个定时器中添加了setTimeout(200)想要在每次执行完一个动画后暂停一段时间,但是最后的效果是全部动画整体移动(在定时器中的输出语句也是同步全部输出),我原本以为每个定时器都会在上一个循环结束后才会执行,但是循环里全部的定时器都是同步执行的,搞蒙了一段时间,最后感觉是js对循环有优化,不过这个问题也很好解决,每个定时器都乘上一个倍数就可以分开了