逻辑
用两个伪元素遮罩文字,一个伪元素根据页面背景颜色设置,另一个做光标线,利用文字长度配合steps函数设置两个伪元素动画属性实现。
具体看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>打字效果</title>
<style>
*{
margin: 0;
padding: 0;
}
body{
display: flex;
height: 100vh;
justify-content: center;
align-items: center;
background-color: black;
color: white;
}
/* 在body上注册css变量,为了配合js获取文字长度配合steps函数实现动态文字长度 */
body{
--i: 0;
}
p{
position: relative;
}
/* 这两个伪元素会根据p的大小宽度来遮罩p */
p:before,p:after{
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
p:before{
/* 这里把遮罩在文字上面的一个伪元素背景设置为和body背景色一样的颜色,
伪元素配合下面动画和关键帧一直往右走,就可以实现一个一个文字出来的效果 */
background-color: black;
/* steps 函数指定一个阶跃函数
第一个参数指定了时间函数中的间隔数量(必须是正整数)
第二个参数可选,接受 start 和 end 两个值,指定在每个间隔的起点或是终点发生阶跃变化,默认为 end
*/
/* 给1s是为了一开始先闪1s */
animation: dong 5s steps(var(--i)) 1s forwards;
}
@keyframes dong {
from{
left: 0;
}
to{
left: 100%;
}
}
p:after{
width: 1.5px;
background-color: white;
animation:
/* 这里可以直接套用上面的动画属性值,因为我们定义的背景伪元素和光标线都是在同一定位,而且需要一起移动 */
dong 5s steps(var(--i)) 1s forwards,
/* 这里使用infinite是让光标线一直闪 */
shan 1s steps(var(--i)) infinite;
}
@keyframes shan {
from{
background: transparent;
}
50%{
background-color: #fff;
}
to{
background: transparent;
}
}
</style>
</head>
<body>
<p>太爱了,所以我,没有哭,没有说</p>
<script>
// 加js实现动态化文字长度
//这里主要是获取body上注册的css变量
const body = document.querySelector('body')
const p = document.querySelector('p');
/*
JS与CSS变量进行交互
设置css变量值:元素.style.setProperty('css变量名',css变量值)
*/
body.style.setProperty('--i',p.innerText.length);
</script>
</body>
</html>