本篇文章手把手教大家,一步步使用纯CSS绘制一个中国结,并给这个中国结添加红包雨动画效果,希望对大家有所帮助!
|
本篇文章手把手教大家,一步步使用纯CSS绘制一个中国结,并给这个中国结添加红包雨动画效果,希望对大家有所帮助!
春节是中国人最重要的节日,春节期间的习俗也非常多,东西南北各不相同。 为了增添年味,过年时家家户户会置办各种年货和装饰品,把家里营造得红红火火,红灯笼,红对联,红福字,以及红色的中国结。
中国结原材料是简简单单的红绳,经过古人的巧妙构思,编织成一个菱形网格的样子。网格上的绳线紧紧连接在一起,象征一家人团结和睦,幸福美满。
那么如何用CSS来实现一个中国结呢? 先看最终效果。
如此 Amazing 的效果,你也可以做出来,下面让我们开始吧! 一、编码之前1. 搜集素材,越简洁越好先从网上搜一张中国结的图片,中国结的样式不止一种,我们选择一种最经典的中国结的编织样式。 图片的质量决定了最后成品的质量,下面就是一张比较整洁,结构清晰的中国结图片。供我们写CSS时参考使用。
2. 观察细节,构思实现的可能性有了图片就可以开始写代码了吗?当然不是。 首先回想一下现在要做的事:用CSS画个中国结。 你真的想好了吗?这是一个可以实现的目标吗?想象一下,当你的领导给你布置一个任务:让手机壳根据APP的主题色而变色。你会直接开始写代码吗? 你会想两个问题:
这是一个比较极端的例子,上面两条都无法实现。回到CSS和这张中国结的图片。我们首先要想的是,我们应该用哪些CSS技术,来实现这个图片。你现在回过头仔细观察一下上面的图片。 经过短暂的观察,我们发现这样一些要点:
然后就是预想一下实现原理:
3. 结构拆分,化整为零上面是从技术角度从整体观察,下面就是对整个图片进行拆分,先确定其
这样我们得到了 <div class="chinese-knot">
<div class="grid"></div>
<div class="ring-small">
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
</div>
<div class="ring-big">
<i><b></b></i>
<i><b></b></i>
</div>
<div class="cross-node">
<div class="node">
<i></i>
<i></i>
<i></i>
<i></i>
</div>
<div class="node">
<i></i>
<i></i>
<i></i>
<i></i>
</div>
</div>
<div class="header">
<i></i>
<b></b>
<span></span>
</div>
<div class="footer">
<b></b>
<b></b>
<div class="tassels">
<i></i>
<i></i>
</div>
</div>
</div>实际编码当中, 二、CSS逐个实现中国结部件1. 网格网格最终效果是个菱形,也就是正方形旋转了
先设定一个变量,表示绳子的宽度,我们设为 :root {
--width: 1.7vh;
}垂直和水平都各有 :root {
--width: 1.7vh;
--grid-width: calc(var(--width) * 16);
}
.grid {
width: var(--grid-width);
height: var(--grid-width);
}给 body{
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #1d1e22;
overflow: hidden;
}再给
这样屏幕正中间就出现了一个白色方块,下面我们把白色背景改成 :root{
--width: 1.7vh;
--red-1: #f40001;
--red-2: #d40000;
--red-3: #8c0703;
--rope:
var(--red-3),
var(--red-2) calc(var(--width) * 0.25),
var(--red-1) calc(var(--width) * 0.45),
var(--red-1) calc(var(--width) * 0.55),
var(--red-2) calc(var(--width) * 0.75),
var(--red-3) var(--width);
--grid-width: calc(var(--width) * 16);
--bg-line: linear-gradient(90deg, var(--rope), transparent var(--width)) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
}
.grid{
width: var(--grid-width);
height: var(--grid-width);
background: var(--bg-line);
}就得到了下面的效果:
可能你有点蒙圈。发生了什么事情? 还是让事情变得简单点,我们先画一根不带渐变的红线: .grid{
background: linear-gradient(
90deg,
var(--red-1),
var(--red-1) var(--width),
transparent var(--width)
);
}
先是一个线性渐变 但这不太像根绳子,让红线渐变起来: .grid{
background: linear-gradient(
90deg,
var(--red-3),
var(--red-2) calc(var(--width) * 0.25),
var(--red-1) calc(var(--width) * 0.45),
var(--red-1) calc(var(--width) * 0.55),
var(--red-2) calc(var(--width) * 0.75),
var(--red-3) var(--width),
transparent var(--width)
);
}
这样就得到了一根有一点点立体效果的绳子。可是怎么让它横向重复 .grid{
background: linear-gradient(
90deg,
var(--red-3),
var(--red-2) calc(var(--width) * 0.25),
var(--red-1) calc(var(--width) * 0.45),
var(--red-1) calc(var(--width) * 0.55),
var(--red-2) calc(var(--width) * 0.75),
var(--red-3) var(--width),
transparent var(--width)
) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
}大家来找茬:这段代码和上一段有什么不同?眼尖的你可能已经看出来了,多了这一行: 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5) 以
这样一个小方块,在垂直和水平方向上重复,就得了我们想要的结果:
可是我们想要的是网格,现在顶多也就算个栅格。 那就使用伪类复制一份,并且旋转 :root{
--width: 1.7vh;
--red-1: #f40001;
--red-2: #d40000;
--red-3: #8c0703;
--rope:
var(--red-3),
var(--red-2) calc(var(--width) * 0.25),
var(--red-1) calc(var(--width) * 0.45),
var(--red-1) calc(var(--width) * 0.55),
var(--red-2) calc(var(--width) * 0.75),
var(--red-3) var(--width);
--grid-width: calc(var(--width) * 16);
--bg-line: linear-gradient(90deg, var(--rope), transparent var(--width)) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
}
.grid {
width: var(--grid-width);
height: var(--grid-width);
background: var(--bg-line);
&:after {
content: "";
display: block;
width: var(--grid-width);
height: var(--grid-width);
background: var(--bg-line);
transform: rotate(90deg);
}
}
对比一下参考图片:
不能说完全不相干,但是人家一看就经过了能工巧匠的编织,咱们这只能算简单的叠加,怎么才能让上面变成下面呢? 经过仔细的观察,发现只要把上面一层横着的线,稍加一些遮挡就能实现交叉编织的效果。用哪个css属性实现呢?那就只有 下图蓝色框是需要遮挡的部分,绿色框是需要重复的部分。
仔细分析一下绿框的构成:
本质上是在一个
这些函数都可以和 用
CSS实现如下: :root{
...
--conic: #000 0 90deg, transparent 0 100%;
}
.grid {
...
&:after {
...
-webkit-mask: conic-gradient(from 0deg at var(--width) calc(var(--width) * 1.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
conic-gradient(from 90deg at calc(var(--width) * 2.5) 0, var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
conic-gradient(from 180deg at calc(var(--width) * 1.5) var(--width), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
conic-gradient(from 90deg at 0 calc(var(--width) * 2.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3);
}
}预览效果
目前为止完整代码 :root{
--width: 1.7vh;
--red-1: #f40001;
--red-2: #d40000;
--red-3: #8c0703;
--rope:
var(--red-3),
var(--red-2) calc(var(--width) * 0.25),
var(--red-1) calc(var(--width) * 0.45),
var(--red-1) calc(var(--width) * 0.55),
var(--red-2) calc(var(--width) * 0.75),
var(--red-3) var(--width);
--grid-width: calc(var(--width) * 16);
--bg-line: linear-gradient(90deg, var(--rope), transparent var(--width)) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
--conic: #000 0 90deg, transparent 0 100%;
}
body{
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #1d1e22;
overflow: hidden;
}
.grid {
width: var(--grid-width);
height: var(--grid-width);
background: var(--bg-line);
&:after {
content: "";
display: block;
width: var(--grid-width);
height: var(--grid-width);
background: var(--bg-line);
transform: rotate(90deg);
-webkit-mask: conic-gradient(from 0deg at var(--width) calc(var(--width) * 1.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
conic-gradient(from 90deg at calc(var(--width) * 2.5) 0, var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
conic-gradient(from 180deg at calc(var(--width) * 1.5) var(--width), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
conic-gradient(from 90deg at 0 calc(var(--width) * 2.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3);
}
}<div class="grid"></div> 没错,这个图形,只用了 但是只有网格还不够,让我们继续。 2. 半圆环回头看一下参考图:
嗯,环形渐变,那就是 <div class="ring-small">
<i></i>
</div>.ring-small {
i {
position: absolute;
width: calc(var(--width) * 2.5);
height: calc(var(--width) * 1.5);
background: radial-gradient(
circle at 50% 100%,
transparent calc(var(--width) * 0.25),
var(--red-3) calc(var(--width) * 0.25),
var(--red-2) calc(var(--width) * (0.25 + 0.25)),
var(--red-1) calc(var(--width) * (0.25 + 0.45)),
var(--red-1) calc(var(--width) * (0.25 + 0.55)),
var(--red-2) calc(var(--width) * (0.25 + 0.75)),
var(--red-3) calc(var(--width) * (0.25 + 1)),
transparent calc(var(--width) * (0.25 + 1))
);
}
}
这样就得到了半个环形图,让我们使用定位把它和网格结合看看 /* 先给最外层加个相对定位,后面的绝对定位都相对这一层 */
.chinese-knot {
width: var(--grid-width);
height: var(--grid-width);
position: relative;
}
.ring-small {
i {
position: absolute;
top: calc(var(--width) * -1.5);
left: calc(var(--width) * 3);
}
}
对比素材图,发现环形不是直接紧贴在网格上的,而是先延伸了一小段直线,再接的曲线。那我们就给它增个高吧: .ring-small {
i {
&:before,
&:after {
content: "";
position: absolute;
bottom: calc(var(--width) * -0.5 + 1px);
width: var(--width);
height: calc(var(--width) * 0.5);
background: var(--bg-line);
}
&:after {
right: 0;
}
}
}上面使用两个伪类,为半圆环加了两截高度为
接着复制 <div class="chinese-knot">
<div class="grid"></div>
<div class="ring-small">
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
</div>
</div>.ring-small {
i {
position: absolute;
width: calc(var(--width) * 2.5);
height: calc(var(--width) * 1.5);
background: radial-gradient(
circle at 50% 100%,
transparent calc(var(--width) * 0.25),
var(--red-3) calc(var(--width) * 0.25),
var(--red-2) calc(var(--width) * (0.25 + 0.25)),
var(--red-1) calc(var(--width) * (0.25 + 0.45)),
var(--red-1) calc(var(--width) * (0.25 + 0.55)),
var(--red-2) calc(var(--width) * (0.25 + 0.75)),
var(--red-3) calc(var(--width) * (0.25 + 1)),
transparent calc(var(--width) * (0.25 + 1))
);
&:before,
&:after {
content: "";
position: absolute;
bottom: calc(var(--width) * -0.5 + 1px);
width: var(--width);
height: calc(var(--width) * 0.5);
background: var(--bg-line);
}
&:after {
right: 0;
}
&:nth-child(-n + 4) {
top: calc(var(--width) * -2 + 2px);
}
&:nth-child(1) {
left: calc(var(--width) * 3);
}
&:nth-child(2) {
left: calc(var(--width) * 6);
}
&:nth-child(3) {
left: calc(var(--width) * 9);
}
&:nth-child(4) {
left: calc(var(--width) * 12);
}
&:nth-child(-n + 8):nth-child(n + 5) {
bottom: calc(var(--width) * -2 + 2px);
transform: rotate(180deg);
}
&:nth-child(5) {
left: calc(var(--width) * 1.5);
}
&:nth-child(6) {
left: calc(var(--width) * 4.5);
}
&:nth-child(7) {
left: calc(var(--width) * 7.5);
}
&:nth-child(8) {
left: calc(var(--width) * 10.5);
}
&:nth-child(-n + 12):nth-child(n + 9) {
left: calc(var(--width) * -2.5 + 2px);
transform: rotate(-90deg);
}
&:nth-child(9) {
top: calc(var(--width) * 3.5);
}
&:nth-child(10) {
top: calc(var(--width) * 6.5);
}
&:nth-child(11) {
top: calc(var(--width) * 9.5);
}
&:nth-child(12) {
top: calc(var(--width) * 12.5);
}
&:nth-child(-n + 16):nth-child(n + 13) {
right: calc(var(--width) * -2.5 + 2px);
transform: rotate(90deg);
}
&:nth-child(13) {
top: calc(var(--width) * 2);
}
&:nth-child(14) {
top: calc(var(--width) * 5);
}
&:nth-child(15) {
top: calc(var(--width) * 8);
}
&:nth-child(16) {
top: calc(var(--width) * 11);
}
}
}就得到了这样的效果
哈哈,很像下水管道~ 3. 四分之三圆环还是先看素材:
嗯,不得不怀疑网易云的 LOGO 的灵感是不是就是中国结。
单个环形已经实现了,两个环也不难吧: <div class="ring-big">
<i><b></b></i>
</div>.ring-big {
i {
position: absolute;
width: calc(var(--width) * 6);
height: calc(var(--width) * 6);
b {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: radial-gradient(
circle at 50% 50%,
transparent calc(var(--width) * 0.5),
var(--red-3) calc(var(--width) * 0.5),
var(--red-2) calc(var(--width) * (0.5 + 0.25)),
var(--red-1) calc(var(--width) * (0.5 + 0.45)),
var(--red-1) calc(var(--width) * (0.5 + 0.55)),
var(--red-2) calc(var(--width) * (0.5 + 0.75)),
var(--red-3) calc(var(--width) * (0.5 + 1)),
transparent calc(var(--width) * (0.5 + 1)),
transparent calc(var(--width) * 2),
var(--red-3) calc(var(--width) * 2),
var(--red-2) calc(var(--width) * (2 + 0.25)),
var(--red-1) calc(var(--width) * (2 + 0.45)),
var(--red-1) calc(var(--width) * (2 + 0.55)),
var(--red-2) calc(var(--width) * (2 + 0.75)),
var(--red-3) calc(var(--width) * (2 + 1)),
transparent calc(var(--width) * (2 + 1))
);
}
}
}
为什么 .ring-big {
i {
...
b {
...
clip-path: polygon(0 0, 100% 0, 100% 50%, 50% 50%, 50% 100%, 0 100%);
}
&:before,
&:after {
content: "";
position: absolute;
top: calc(var(--width) * 3 - 1px);
left: calc(var(--width) * 3.5);
width: calc(var(--width) * 2.5);
height: calc(var(--width) * 0.5 + 2px);
background: repeating-linear-gradient(
90deg,
var(--red-3),
var(--red-2) calc(var(--width) * 0.25),
var(--red-1) calc(var(--width) * 0.45),
var(--red-1) calc(var(--width) * 0.55),
var(--red-2) calc(var(--width) * 0.75),
var(--red-3) var(--width),
transparent var(--width),
transparent calc(var(--width) * 1.5)
);
}
&:after {
transform: rotate(90deg);
transform-origin: left top;
top: calc(var(--width) * 3.5);
left: calc(var(--width) * 3.5 + 1px);
}
}
}
复制一份并定位: .ring-big {
i {
...
&:nth-child(1) {
left: calc(var(--width) * -3.5);
top: calc(var(--width) * -3.5);
}
&:nth-child(2) {
left: auto;
top: auto;
right: calc(var(--width) * -3.5);
bottom: calc(var(--width) * -3.5);
transform: rotate(180deg);
}
}
}
到这里,工作的一半就已经完成了~继续 4. 十字结
这个图形,相对于上面几个,已经没什么难度了,五个 中间的正方形,用父级本身实现,里面周围四个,用四个子 <div class="cross-node">
<div class="node">
<i></i>
<i></i>
<i></i>
<i></i>
</div>
<div class="node">
<i></i>
<i></i>
<i></i>
<i></i>
</div>
</div>.cross-node {
.node {
position: absolute;
z-index: 2;
width: var(--width);
height: var(--width);
background: var(--bg-line);
i {
position: absolute;
width: var(--width);
height: var(--width);
background: var(--bg-line);
transform: rotate(90deg);
&:nth-child(1) {
left: calc(var(--width) * -1);
}
&:nth-child(2) {
left: var(--width);
}
&:nth-child(3) {
top: calc(var(--width) * -1);
}
&:nth-child(4) {
top: var(--width);
}
}
&:nth-child(1) {
right: calc(var(--width) * -1);
top: calc(var(--width) * -1);
}
&:nth-child(2) {
left: calc(var(--width) * -1);
bottom: calc(var(--width) * -1);
}
}
}
5. 挂绳前面我们都是让中国结处于一个斜躺的姿态,写头部和尾部之前,让我们先把它摆正: .chinese-knot {
...
transform: rotate(-45deg) translate(calc(var(--width) * 4), calc(var(--width) * -4));
}
回头看素材图:
先确定一下 <div class="header">
<i></i>
<b></b>
<span></span>
</div>
:root {
--yellow-1: #fced00;
--yellow-2: #f28a00;
--yellow-3: #da571b;
--bg-yellow: linear-gradient(
90deg,
var(--yellow-3),
var(--yellow-2) 20%,
var(--yellow-1) 40%,
var(--yellow-1) 60%,
var(--yellow-2) 80%,
var(--yellow-3) 100%
);
}
.header {
position: absolute;
right: 0;
top: 0;
transform: rotate(45deg);
i {
position: absolute;
bottom: calc(var(--width) * 1);
left: calc(var(--width) * -0.5);
width: calc(var(--width) * 1);
height: calc(var(--width) * 2);
background: var(--bg-line);
&:before {
content: "";
display: block;
height: calc(var(--width) * 0.5);
background: var(--bg-yellow);
}
}
}然后是圆环: .header {
...
b {
position: absolute;
bottom: calc(var(--width) * 3);
left: calc(var(--width) * -1.5);
width: calc(var(--width) * 3);
height: calc(var(--width) * 3);
background: radial-gradient(
circle at 50%,
transparent calc(var(--width) * 0.75),
var(--red-3) calc(var(--width) * 0.75),
var(--red-2) calc(var(--width) * (0.75 + 0.15)),
var(--red-1) calc(var(--width) * (0.75 + 0.3)),
var(--red-1) calc(var(--width) * (0.75 + 0.45)),
var(--red-2) calc(var(--width) * (0.75 + 0.6)),
var(--red-3) calc(var(--width) * (0.75 + 0.75)),
transparent calc(var(--width) * (0.75 + 0.75))
);
}
}最后是长的吊绳: .header {
...
span {
position: absolute;
bottom: calc(var(--width) * 5);
left: calc(var(--width) * -0.25);
width: calc(var(--width) * 0.5);
height: calc(var(--width) * 30);
background: linear-gradient(90deg, var(--red-2), var(--red-1) 20%, var(--red-2) 70%, var(--red-3));
border-radius: calc(var(--width) * 0.25);
}
}单独效果
整体效果
6. 流苏
确定 <div class="footer">
<b></b>
<b></b>
<div class="tassels">
<i></i>
<i></i>
</div>
</div>可以看到,流苏部分,有两个弯曲的 .footer {
position: absolute;
left: 0;
bottom: 0;
b {
position: absolute;
width: calc(var(--width) * 15);
height: calc(var(--width) * 15);
background: radial-gradient(
circle at 50%,
transparent calc(var(--width) * 6.5),
var(--red-3) calc(var(--width) * 6.5),
var(--red-2) calc(var(--width) * (6.5 + 0.25)),
var(--red-1) calc(var(--width) * (6.5 + 0.45)),
var(--red-1) calc(var(--width) * (6.5 + 0.55)),
var(--red-2) calc(var(--width) * (6.5 + 0.75)),
var(--red-3) calc(var(--width) * (6.5 + 1)),
transparent calc(var(--width) * (6.5 + 1))
);
}
}
加上裁剪并定位: .footer {
...
b {
...
&:nth-child(1) {
left: calc(var(--width) * -8.5);
top: calc(var(--width) * 1);
clip-path: polygon(50% 0, 50% 50%, 10% 0);
}
&:nth-child(2) {
left: calc(var(--width) * -16);
top: calc(var(--width) * -6.5);
clip-path: polygon(100% 50%, 50% 50%, 100% 90%);
}
}
}
两个小尾巴就实现了。 最后是流苏。先画一下背景上的垂直细线,这里我们用 .footer {
.tassels {
i {
position: absolute;
width: calc(var(--width) * 2.5);
height: calc(var(--width) * 14);
background: var(--red-2) repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.2) 1px, transparent 1px, transparent 3px) 50% 50% / 3px 1px;}
}
}
再蒙上一层黄色的装饰: .footer {
.tassels {
i {
...
&:before {
content: "";
position: absolute;
top: calc(var(--width) * 0.5);
width: 100%;
height: calc(var(--width) * 3.6);
background: var(--bg-yellow);
clip-path: polygon(0 0, 100% 0, 100% 10%, 0 10%, 0 15%, 100% 15%, 100% 85%, 0 85%, 0 90%, 100% 90%, 100% 100%, 0 100%, 0 0);
}
}
}
上面代码中使用
最终效果:
三、加点动画本来到这里就应该结束了。但是我想让这个中国结有点实际用途,比如加点交互什么的。 红包也是春节的习俗之一,那就加一个拉一下中国结掉落红包雨的特效吧~ 1. 拉一下给中国结在 .chinese-knot {
width: var(--grid-width);
height: var(--grid-width);
position: relative;
transform: rotate(-45deg) translate(calc(var(--width) * 4), calc(var(--width) * -4));
cursor: pointer;
-webkit-tap-highlight-color: transparent;
transition: all 0.5s;
&:active {
transform: rotate(-45deg) translate(calc(var(--width) * 2), calc(var(--width) * -2));
}
}
2. 画个红包先搜索一个红包素材:
观察一下红包结构,深红背景,浅红弧形开口,加一个黄色圆形封口,上面写着一个繁体的开字。 我们可以先确定 <div class="rain"> <i></i> </div> 一个标签怎么实现上面提到的三种元素呢?看代码: .rain {
position: absolute;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-around;
i {
position: relative;
display: block;
width: calc(var(--width) * 5);
height: calc(var(--width) * 8);
background: var(--red-3);
border-radius: calc(var(--width) * 0.4);
overflow: hidden;
box-shadow: 0 calc(var(--width) * 1) calc(var(--width) * 1) rgba(0, 0, 0, 0.3);
&:before {
content: "";
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
width: calc(var(--width) * 8);
height: calc(var(--width) * 8);
background: var(--red-1);
opacity: 0.5;
border-radius: 50%;
}
&:after {
content: "開";
position: absolute;
left: 50%;
transform: translate(-50%, 140%);
width: calc(var(--width) * 2);
height: calc(var(--width) * 2);
background: var(--yellow-2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-style: normal;
font-size: calc(var(--width) * 0.5);
color: var(--yellow-1);
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.1);
}
}
}
使用 一个红包完成了,再复制 9 个: <div class="rain"> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> </div>
这样就得到了 10 个固定在顶部,并且整齐排列的红包了。 3. 红包雨动画下雨嘛,从上往下运动就好了: .rain {
...
i {
...
animation: fall 3s ease-in infinite;
}
}
@keyframes fall {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(0, 100vh);
}
}
聪明的你估计已经猜到了这样的结果:谁家的雨是这样齐刷刷的下来的? 那我们就红包的垂直位置错落一点,使用 .rain {
...
i {
...
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
top: random(60) + vh;
}
}
}
}
额,效果怎么和想象的不一样。依旧还是齐刷刷下落,只不过是"错落"的齐刷刷。 那我们让每个红包的开始时间也随机不就行了嘛: .rain {
...
i {
...
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
top: random(60) + vh;
animation-delay: random(30) * 0.1s;
}
}
}
}
嗯,好了一点点。但是有一个问题,屏幕上的雨点,有时候很多,有时候很少,不够均匀。那我们把动画的持续时间也随机会怎么样呢? .rain {
...
i {
...
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
top: random(60) + vh;
animation-delay: random(30) * 0.1s;
animation-duration: random(10) * 0.1s + 2s; /* 2s ~ 3s 之间随机 */
}
}
}
}
终于更像雨了~ 但是现在雨滴是凭空出现的,很生硬,我们只要把开始的位置挪到 .rain {
...
top: -100vh;
}
@keyframes fall {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(0, 200vh);
}
}
这样就有了源源不断下落的效果。 4. 拉一下触发红包雨
我们就要运用 样式可以触发了,那如何触发动画呢?
<input type="checkbox" id="switch"> <label class="chinese-knot" for="switch">...</label> <div class="rain">...</div> .rain {
...
i {
...
animation: fall 3s ease-in infinite;
/* 默认不播放动画 */
animation-play-state: paused;
}
}
#switch {
visibility: hidden;
pointer-events: none;
}
/* checkbox 选中时播放动画 */
#switch:checked ~ .rain i {
animation-play-state: running;
}
/* 点击时重置动画,否则取消checkbox选中状态,动画会中止并停留在当前位置 */
.chinese-knot:active ~ .rain i {
animation: none;
}上面的
效果很不错,我们再给红包雨下落时加个背景,以提醒用户当前的状态。并且下红包雨时,调低中国结的透明度,以突出红包的存在感。 <input type="checkbox" id="switch"> <div class="bg"></div> <label class="chinese-knot" for="switch">...</label> <div class="rain">...</div> .bg {
position: absolute;
left: 0;
top: 0;
height: 100vh;
width: 100vw;
background: linear-gradient(0deg, #171a4b, #96367f);
opacity: 0;
transition: all 0.5s;
}
#switch:checked ~ .bg {
opacity: 1;
}
#switch:checked ~ .chinese-knot {
opacity: 0.2;
&:hover {
opacity: 0.5;
}
}
完结撒花~~~ 总结这篇文章整理了我从搜集素材开始,创作一个作品的全部过程,代码写了一天,这篇文章写了半天。希望能让 CSS 初学者对 CSS 燃起兴趣,也希望让接触了一段时间 CSS 的朋友获得一些灵感和帮助。 (学习视频分享:css视频教程) 以上就是手把手带你使用纯CSS绘制一个中国结,并添加动画效果!的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |
