2.animated-navigation
实现效果:
- 倒计时321后显示go
- 数字依次从x轴负方向,顺时针倒下去
- x=y
- 第一个数(0,y)—>(-x,0)
- 第一个数字倒下去的同时,第二个数从x轴正方向升起
- 第二个数(x,0)—>(0,y)
- 就像八百一千米体测开始一样😜
实现步骤:
- 进入页面,显示倒计时321,倒计时时间到,显示Go
- 点击Ready后,重新倒计时
- 倒计时升起倒下动画
- 进入页面后,先让倒计时显示,Go隐藏
- 第一个数3升起后,判断
- 动画= 升起动画goIn
- 当前数组元素的索引0 ! = 当前数组元素3
- 第一个数3倒下goOut
- 第一个数3倒下后,判断
- 动画= 升起动画goOut
- num.nextElementSibling = < span class=“out”>2< /span>
- 第二个数2升起goIn
- 第二个数2升起后,判断
- 动画= 升起动画goIn
- 当前数组元素的索引1 ! = 当前数组元素2
- 第二个数2倒下goOut
- 第二个数2倒下后,判断
- 动画= 升起动画goOut
- num.nextElementSibling = 1
- 第三个数1升起goIn
- 第三个数1升起后,判断
- 动画 = 升起动画goIn
- 当前数组元素的索引1 = 当前数组元素1 不满足条件
- 属于else:让倒计时隐藏,让GO出现
知识点:
使用classList添加class、删除class、查询class:
- add( 新):添加一个或多个类名,已存在,取消添加;
- num[0].classList.add(‘in’):给第一个num添加类名为in的类。
- contains(旧):检查类属性中有无指定的类名,返回true 、false;
- remove(旧):移除已经存在的类名;
- toggle(类名);classList中存在指定的值,则删除它,否则,添加它;
- 当只有一个参数时:切换 class的值; 🎉
- 类存在:删除它,返回false;不存在:添加它,返回true。
- 第二个参数:计算结果: true,添加指定的类;计算结果 : false,则删除此类名。
- boxesContainer.classList.toggle(‘big’)):
- big被设置则删除它big,否则添加它big。
- classList.replace( 旧,新 ):类名替换。
行内块、行内、块级元素
1.块级元素(可独块)block
- 独占一行
- 宽度:父元素宽度(默认)
- 高度:由内容撑开(默认)
- 可设置宽高
2.行内元素(不可多行)inline
- 一行显多个,不换行
- 宽度由内容撑开
- 不可设宽高
- (水平方向)padding和margin可以设置
3.行内块元素(可多行内块)inline-block
- 一行多个(中间存在间隙)
- 可设宽高
nextSibling 和nextElementSibling:
1.nextSibling
- 返回指定节点之后的下一个兄弟节点。
- 相同节点树层中的下一个节点。
- 包括文本节点、注释节点(回车、换行、空格、文本)
- 空格、回车 = 文本,也属于文本。
2.nextElementSibling
- 只返回元素节点之后的下一个兄弟元素节点
- 相同节点树层中的下一个元素节点
- 不包括文本节点、注释节点
- 只读属性
其他知识点:
- value:用于设置或者返回属性的值。
- 在运行倒计时,要设置遍历倒计时321,将属性值都设空;否则第二次执行时,会暂停在第一次的最后结果0。🎉
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
margin: 0;
height: 100vh;
overflow: hidden;
background-color: rgb(161, 158, 228);
}
h4 {
font-size: 20px;
margin: 5px;
/* 所有字母变大写 */
text-transform: uppercase;
}
.counter,
.final {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.counter.hide {
transform: translate(-50%, -50%) scale(0);
animation: hide .2s ease-out;
}
@keyframes hide {
0% {
transform: translate(-50%, -50%) scale(1);
}
100% {
transform: translate(-50%, -50%) scale(0);
}
}
.final {
transform: translate(-50%, -50%) scale(0);
}
.final.show {
transform: translate(-50%, -50%) scale(1);
animation: show .2s ease-out;
}
@keyframes show {
0% {
transform: translate(-50%, -50%) scale(0);
}
30% {
transform: translate(-50%, -50%) scale(1.4);
}
100% {
transform: translate(-50%, -50%) scale(1);
}
}
.nums {
color: rgb(53, 15, 203);
font-size: 50px;
position: relative;
overflow: hidden;
width: 250px;
height: 50px;
}
.nums span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%)rotate(120deg);
/* 旋转基点为底部中心 */
transform-origin: bottom center;
}
.nums span.in {
transform: translate(-50%, -50%) rotate(0deg);
animation: goIn .5s ease-in-out;
}
.nums span.out {
animation: goOut .5s ease-in-out;
}
@keyframes goIn {
0% {
transform: translate(-50%, -50%) rotate(120deg);
}
30% {
/* 会有回弹的感觉由-20--10--0 */
transform: translate(-50%, -50%) rotate(-20deg);
}
60% {
transform: translate(-50%, -50%) rotate(10deg);
}
100% {
transform: translate(-50%, -50%) rotate(0deg);
}
}
@keyframes goOut {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
60% {
transform: translate(-50%, -50%) rotate(20deg);
}
100% {
transform: translate(-50%, -50%) rotate(-120deg);
}
}
#replay {
background-color: rgb(95, 39, 193);
border-radius: 3px;
/* 去掉button的边框黑线 */
border: none;
color: aliceblue;
padding: 5px;
text-align: center;
display: inline-block;
cursor: pointer;
transition: all .3s;
}
#replay span {
cursor: pointer;
display: inline-block;
position: relative;
transition: .3s;
}
#replay span::after {
/* 在span后面添加》 */
content: '\00bb';
position: absolute;
opacity: 0;
top: 0;
right: -20px;
transition: .5s;
}
#replay:hover span {
padding-right: 25px;
}
#replay:hover span::after {
opacity: 1;
right: 0;
}
<div class="counter">
<div class="nums">
<span class="in">3</span>
<span>2</span>
<span>1</span>
<span>0</span>
</div>
<h4>Get Ready</h4>
</div>
<div class="final">
<h1>GO</h1>
<button id="replay">
<span>Replay</span>
</button>
</div>
const nums = document.querySelectorAll('.nums span')
const counter = document.querySelector('.counter')
const final = document.querySelector('.final')
const replay = document.querySelector('#replay')
// 隐藏和显示切换
function resetDOM () {
// 让倒计时显示,让Go隐藏
counter.classList.remove('hide')
final.classList.remove('show')
// 遍历倒计时321,将属性值都设空,否则第二次执行的时候,会暂停在第一次的最后结果0
nums.forEach((num) => {
num.classList.value = ''
})
num[0].classList.add('in')
}
// 页面一加载出来就要显示倒计时动画
runAnimation()
// 倒计时移动动画
function runAnimation () {
nums.forEach((num, idx) => {
const nextToLast = nums.length - 1
num.addEventListener('animationend', (e) => {
// 动画名=goIn且当前数组元素的索引!=当前数组元素
if (e.animationName === 'goIn' && idx !== nextToLast) {
// console.log(idx)
// console.log(nextToLast)
// 删除in类名,添加out类名(倒计时倒下)
num.classList.remove('in')
num.classList.add('out')
// 如果动画名=goOut并且等于返回下一个兄弟元素节点
} else if (e.animationName === 'goOut' && num.nextElementSibling) {
console.log(num.nextElementSibling)
// 给下一个数添加动画in(倒计时升起)
num.nextElementSibling.classList.add('in')
} else {
// 让倒计时隐藏,让GO出现
counter.classList.add('hide')
final.classList.add('show')
}
})
})
}
// 点击Replay按钮,重新执行倒计时动画
replay.addEventListener('click', () => {
resetDOM()
runAnimation()
})
倒计时结束后: