持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
前言
跑马灯大家都见过吧?只是单单的跑马灯有点太炫了,看久了眼睛就亮瞎了,今天我带大家手把手用 CSS 制作一个百看不腻的跑马灯,不信你往下瞅瞅?
本文将会带大家学到以下知识点:
- 垂直水平居中方式
text-shadow
的用法- CSS 变量的简单应用
- 旋转属性
rotate
的用法 transform-origin
改变旋转的原点animation
中steps
的用法
重置样式
首先还是老规矩,我们先将样式重置一下,避免不同浏览器的效果不一致。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ps:通配符会匹配页面上的 所有元素 ,相当于将整颗 DOM 树都进行了遍历,效率很低 ,大家日常开中不要这么写,咱们写 demo 自己知道就好了。
背景板
我们会后续的效果会展示在视口中央位置,因此,为了撑开 body
的高度,我们需要将它的高度设置为 100vh,也就是与视口同高。
其次,在 body
元素 宽高确定 的情况下,我们可以使用 flex
布局来实现 水平垂直居中 的效果。
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #222;
}
到这里为止都比较基础,但是小伙伴们千万别不重视,细节决定成败。
文字居中
接下来我们绘制文字,这里我通过 h3
标签,内嵌 span
标签实现的。这样刚好用上了 h3
的粗标题效果。
<h3>CatWatermelon is <span>handsome</span></h3>
接下来我们要实现文字居中的效果了,这时有的小伙伴会问:刚刚上文不是已经让 body
设置了水平垂直居中吗,还要做?
上文确实设置了,但是我们想要的效果是文字叠加在特效上的,什么意思呢?我们看看下面这张图:
如果仅靠上文的手段,最后的成品会是左图那样,特效在上,文字在下,而我们想要的是文字和特效重叠的效果,那么这就必须让文字绝对的居中了。
这里我们要用到另一个水平垂直居中手段:绝对定位+transform。
h3 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
...
}
什么原理呢?
我们看看上图,这是正常 left: 50%
和 top: 50%
的效果,左边和上面都偏了点,肯定不是我们想要的,除非能让它左边上面都“回去”半个身位。诶,刚刚的 transform
难道就是这个作用?恭喜你,答对了!
我们日常开发中经常使用这套组合去实现水平垂直居中的效果。话不多说,我们回到正题。
发光文字
接下来我们要让 span
标签内的文字“发光”了,具体怎么实现呢?
不知道大家平时开发中 box-shadow
属性用的多不多,我们平时用它进行阴影的绘制,也可以模拟发光效果,不过它是针对 盒子模型 的,也就是整个标签。CSS3 中推出了一个新的属性:text-shadow
,它的效果和 box-shadow
很相似,不同的是前者用于 文字 ,后者用于 盒子。
为了防止有的小伙伴还是没明白,我做了个动图:
从图中可以看到 text-shadow
和 box-shadow
很相似,我们的文字发光效果实际上是用 5 个阴影模拟的。
h3 span {
color: #fff;
font-weight: 500;
text-shadow: 0 0 10px #fff,
0 0 20px #fff,
0 0 30px #fff,
0 0 40px #fff,
0 0 50px #fff;
}
环绕方块
接下来是比较难理解的一个效果了,但是理解了很好做。
我们要做一些环绕文字的方块,我给大家画个示意图。
原理就是将 12 个正方形左上角都放置一个方块,然后每个正方形都进行一定角度的旋转,具体旋转多少度呢?我们知道一圈是 360°,我们有 12 个正方形需要旋转,因此每个正方形的旋转角度为 360 / 12 = 30
。
为了方便计算,我们将 12 个方块都设置一个 CSS 变量 。
<div class="box">
<div class="loader">
<span style="--i:1"></span>
<span style="--i:2"></span>
...
<span style="--i:12"></span>
</div>
<h3>CatWatermelon is <span>handsome</span></h3>
</div>
小方块的外层容器我们用 span
标签来做。
.loader {
position: relative;
width: 150px;
height: 150px;
}
.loader span {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform: rotate(calc(30deg * var(--i)));
}
这里使用到了 rotate
属性来进行旋转,和我们刚刚的示意图一样,
接下来是小方块的制作。
.loader span::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
background: rgba(255, 255, 255, 0.15);
}
这里我们通过将 span
正方形进行 相对定位 ,然后伪元素模拟的小方块进行 绝对定位 ,将小方块定位到左上角的位置。
来看看现在的效果吧:
让方块发光
接下来我们要让部分方块发光,比如每隔两个方块,就有一个方块发光。
具体怎么做呢?首先每隔两块用 CSS 语言怎么理解呢?不知道小伙伴们平时开发的时候有没有用过伪元素?first-child
、last-child
?它们分别表示父元素的第一个子元素以及父元素的最后一个子元素。那么我们如果要访问第二个元素或者是第三个元素,就要用到 nth-child
属性了。
nth-child(n
) 接收一个参数,表示要访问第几个,值得一提的是,它可以传入一个表达式,比如我们要访问 2 的倍数,就可以使用 nth-child(2n+2)
,同理,我们如果要实现每隔两个访问,就要通过 nth-child(3n+3)
来实现了。
我们将小方块添加白色背景,然后发光效果我们可以使用 box-shadow
,用 5 个阴影进行叠加处理。
.loader span:nth-child(3n + 3):before {
background: #fff;
box-shadow: 0 0 10px #fff,
0 0 20px #fff,
0 0 30px #fff,
0 0 40px #fff,
0 0 50px #fff;
}
我们看看此时的效果:
让小方块旋转起来
看到小标题有的小伙伴就乐了:这还不简单?直接 animation + rotate
一把梭。
好像也没错,但是你真的想清楚了吗?我们先来一版看看效果。
.loader span:nth-child(3n + 3):before {
...
animation: animateSquare 2s linear infinite;
}
@keyframes animateSquare {
0%,25% {
transform: rotate(0deg);
}
75%,90%,100% {
transform: rotate(180deg);
}
}
我们分别在 0%、25%、75%、90% 以及 100% 的时候设置不同的旋转角度,让它们有一个速度差的感觉。
从图中我们可以发现小方块们是旋转了没错,但是好像没有想象中那样跑到下一个发光小方块的位置。这是因为 rotate
是以原点位置来进行旋转的,正方形的原点在它的交叉轴的交点位置,因此旋转时是待在原地的。
为了实现这个效果,我们需要用到另一个属性:transform-origin
。
它可以改变我们的原点位置,让物体沿着新的原点进行变换。
我们试试不断加大 transform-origin
的值,看看改变它之后对我们的 rotate
效果有什么影响。
可以发现, transform-origin
的值越大,绕的幅度就越大。
那么我们为了达到当前发光小方块旋转到下一发光小方块的效果,我们就要找一个合适的 transform-origin
值,这个值怎么计算呢?很简单,我们直接设置为正方形长度的一半,也就是 150 / 2 = 75
。我们再看看效果:
这就对了。我们接着走。
发光走马灯
接下来我们就要让发光小方块像走马灯一样,一个亮完后让下一个亮起来。
怎么实现呢?这里有点复杂了,我们先让它们旋转起来吧。
.loader {
...
animation: animate 24s linear infinite;
}
@keyframes animate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
只要给 .loader
类添加一个动画 animate
,并让其在 24 秒内线性循环播放就好了。
这个旋转的动画在 24 秒内会完成绕圈 360° 的动作,我们可以看到它是一步一个脚印循规蹈矩的“走”(这里后面要考,记住了昂)。
但是这不是我们想要的效果,我们不需要它慢慢走,为了模拟走马灯,我们需要发光小方块一次跳一格(一次旋转到一定位置,使其看着像跳了一格)。为此,我们需要将 animation
中的 linear
属性换为 steps(12)
。
别的先不说,我们先看效果:
是不是每个发光小方块都一次跳一格?这是什么原理呢?
这就是 steps
的魔力。如果我们把 linear
比作一步一个脚印,那可以将 steps
比作瞬移,它省略了中间的过程。这么说可能有的小伙伴还是不懂,话不多说,上示意图好吧。
假如我们要在 10 秒内让正方形旋转 90°,那么我们使用 linear
就大概像上图一样(省略过程),是慢慢旋转过去的;而如果我们使用 steps(4)
,就会每 10 / 4 秒时,截取当时正方形形态的 快照 ,共截取 4 张。
我们想要实现小方块一跳一跳的效果,就是每 24 / 2 秒时,截取一次当时状态的快照。为什么是 24 / 2 呢?因为 24 秒旋转 360°,每秒旋转 15°,而我们刚刚的小方块围绕效果是每个正方形旋转 30 * var(--i)
实现的,也就是说每个正方形的旋转度数相差 30°,为了实现瞬移的效果,我们要截取的是 30° 时的快照,也就是每 2 秒截一次,因此 steps
的参数是 12。
.loader {
position: relative;
width: 150px;
height: 150px;
animation: animate 24s steps(12) infinite;
}
码上掘金
Github 源码
juejin-demo/animate-block-demo at main · catwatermelon/juejin-demo (github.com)
结束语
本文就到此结束了,希望大家共同努力,早日拿下 CSS 💪💪。
如果文中有不对的地方,或是大家有不同的见解,欢迎指出 🙏🙏。
如果大家觉得所有收获,欢迎一键三连💕💕。