好使用纯CSS绘制一个中国结并添加动画效果(css,web开发)

时间:2024-05-09 15:45:05 作者 : 石家庄SEO 分类 : web开发
  • TAG :

春节是中国人最重要的节日,春节期间的习俗也非常多,东西南北各不相同。为了增添年味,过年时家家户户会置办各种年货和装饰品,把家里营造得红红火火,红灯笼,红对联,红福字,以及红色的中国结。

好使用纯CSS绘制一个中国结并添加动画效果

中国结原材料是简简单单的红绳,经过古人的巧妙构思,编织成一个菱形网格的样子。网格上的绳线紧紧连接在一起,象征一家人团结和睦,幸福美满。

好使用纯CSS绘制一个中国结并添加动画效果

那么如何用CSS来实现一个中国结呢? 先看最终效果。

好使用纯CSS绘制一个中国结并添加动画效果


如此 Amazing 的效果,你也可以做出来,下面让我们开始吧!

一、编码之前

1. 搜集素材,越简洁越好

先从网上搜一张中国结的图片,中国结的样式不止一种,我们选择一种最经典的中国结的编织样式。图片的质量决定了最后成品的质量,下面就是一张比较整洁,结构清晰的中国结图片。供我们写CSS时参考使用。

好使用纯CSS绘制一个中国结并添加动画效果

2. 观察细节,构思实现的可能性

有了图片就可以开始写代码了吗?当然不是。

首先回想一下现在要做的事:用CSS画个中国结。

你真的想好了吗?这是一个可以实现的目标吗?想象一下,当你的领导给你布置一个任务:让手机壳根据APP的主题色而变色。你会直接开始写代码吗?

你会想两个问题:

  • APP作为一个软件,是否有和手机壳互动的接口

  • 手机壳如果接收到色值,如何变色

这是一个比较极端的例子,上面两条都无法实现。回到CSS和这张中国结的图片。我们首先要想的是,我们应该用哪些CSS技术,来实现这个图片。你现在回过头仔细观察一下上面的图片。

经过短暂的观察,我们发现这样一些要点

  • 中国结的绳子是由渐变色组成,深红,浅红,深红

  • 中间的主体部分由22根相互交叉的绳子组合而成,而且每过一个交叉点就会交换一下层级顺序

  • 有一些环状结构,颜色渐变的过程与直线相同

  • 整体都是红色,以黄色点缀

然后就是预想一下实现原理

  • 直线的颜色渐变,使用 linear-gradient 或者 repeating-linear-gradient

  • 环状渐变,使用 radial-gradient

  • 网格的交叉,使用 mask 遮罩来达到交叉效果

  • 四分之三环以及底部两根弯曲的绳子使用 clip-path 来裁剪

  • 为了使编码更方便,采用 SCSS

  • 许多地方可以使用 ::before ::after 实现,减少html代码

3. 结构拆分,化整为零

上面是从技术角度从整体观察,下面就是对整个图片进行拆分,先确定其 html 结构。

  • 中间像棋盘一样的网格结构,可以作为一个 html 标签

好使用纯CSS绘制一个中国结并添加动画效果

  • 四周16个小半圆,使用16个标签定位实现

好使用纯CSS绘制一个中国结并添加动画效果

  • 两个四分之三圆,放在一组里,使用相同的样式,第二个基于第一个旋转180deg

好使用纯CSS绘制一个中国结并添加动画效果

  • 两个十字结,样式一样,所以也放在一组里

好使用纯CSS绘制一个中国结并添加动画效果

  • 顶部三个小结构,放在一组,外层命名为header

好使用纯CSS绘制一个中国结并添加动画效果

  • 底部左右两部分高度相似,也放在一组,命名为footer

好使用纯CSS绘制一个中国结并添加动画效果

这样我们得到了 html 的结构

<divclass="chinese-knot"><divclass="grid"></div><divclass="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><divclass="ring-big"><i><b></b></i><i><b></b></i></div><divclass="cross-node"><divclass="node"><i></i><i></i><i></i><i></i></div><divclass="node"><i></i><i></i><i></i><i></i></div></div><divclass="header"><i></i><b></b><span></span></div><divclass="footer"><b></b><b></b><divclass="tassels"><i></i><i></i></div></div></div>

实际编码当中,html 并不是一次写成,而是经过不断调整才成为上面这个样子。

二、CSS逐个实现中国结部件

1. 网格

网格最终效果是个菱形,也就是正方形旋转了45deg,我们先不旋转,看看它是什么样子

好使用纯CSS绘制一个中国结并添加动画效果

先设定一个变量,表示绳子的宽度,我们设为--width,这个尺寸很重要,后面所有尺寸都是基于这个宽度,这样后面我们调整整个图形的大小,只要改这一个--width就行了。

:root{--width:1.7vh;}

垂直和水平都各有11根绳,绳子之间的间隙约为绳子宽度的 0.5 倍,所以可以得到网格的宽高都为 11 + 0.5 * 10 = 16 倍的绳子宽度,所以我们可以这样写:

:root{--width:1.7vh;--grid-width:calc(var(--width)*16);}.grid{width:var(--grid-width);height:var(--grid-width);}

body 加上一些样式,让盒子居中,再加一个深色背景

body{margin:0;display:flex;justify-content:center;align-items:center;height:100vh;background:#1d1e22;overflow:hidden;}

再给 .grid 也加一个白色背景色,测试一下:

好使用纯CSS绘制一个中国结并添加动画效果

这样屏幕正中间就出现了一个白色方块,下面我们把白色背景改成11根线的样式:

: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),transparentvar(--width))00/calc(var(--width)*1.5)calc(var(--width)*1.5);}.grid{width:var(--grid-width);height:var(--grid-width);background:var(--bg-line);}

就得到了下面的效果:

好使用纯CSS绘制一个中国结并添加动画效果

可能你有点蒙圈。发生了什么事情?

还是让事情变得简单点,我们先画一根不带渐变的红线:

.grid{background:linear-gradient(90deg,var(--red-1),var(--red-1)var(--width),transparentvar(--width));}

好使用纯CSS绘制一个中国结并添加动画效果

先是一个线性渐变 linear-gradient,然后旋转角度设为90deg,让它从左到右渐变(默认是从下往上),然后起始值设为--red-1(你问我red-1red-3哪来的?效果图上吸来的),在--width处也设置为--red-1,这样就得到了一根宽为 --width 的红线。但这还没完,得接着在--width 处加一个透明transpanrent,这样从--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),transparentvar(--width));}

好使用纯CSS绘制一个中国结并添加动画效果

这样就得到了一根有一点点立体效果的绳子。可是怎么让它横向重复11次,并且间隔0.5倍的--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),transparentvar(--width))00/calc(var(--width)*1.5)calc(var(--width)*1.5);}

大家来找茬:这段代码和上一段有什么不同?眼尖的你可能已经看出来了,多了这一行:

00/calc(var(--width)*1.5)calc(var(--width)*1.5)

/为分界线,左边的含义是background-positoin,右边的含义是background-size

0 0也就是左上角。calc(var(--width) * 1.5) calc(var(--width) * 1.5) 也就是一个正方形,宽度为1.5倍绳宽。

好使用纯CSS绘制一个中国结并添加动画效果

这样一个小方块,在垂直和水平方向上重复,就得了我们想要的结果:

好使用纯CSS绘制一个中国结并添加动画效果

可是我们想要的是网格,现在顶多也就算个栅格。

那就使用伪类复制一份,并且旋转90deg

: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),transparentvar(--width))00/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绘制一个中国结并添加动画效果

不能说完全不相干,但是人家一看就经过了能工巧匠的编织,咱们这只能算简单的叠加,怎么才能让上面变成下面呢?

经过仔细的观察,发现只要把上面一层横着的线,稍加一些遮挡就能实现交叉编织的效果。用哪个css属性实现呢?那就只有mask 了。

下图蓝色框是需要遮挡的部分,绿色框是需要重复的部分。

好使用纯CSS绘制一个中国结并添加动画效果

仔细分析一下绿框的构成:

好使用纯CSS绘制一个中国结并添加动画效果

本质上是在一个3×3的正方形上挖两个1×1的小洞,位置分别是0 01.5 1.5。我们要如何画这样一张图?并把这张图应用到mask上呢?

mask是通过传入的图片进行遮罩处理,而背景图除了传入一张png以外,CSS还内置了几个生成背景图的函数:

  • linear-gradient:线性渐变

  • repeating-linear-gradient:重复线性渐变

  • radial-gradient:径向渐变

  • conic-gradient:圆锥渐变

这些函数都可以和mask配合。这里我们使用conic-gradient实现上面的图形。

conic-gradient 实现上图,思路要反着来:不是在方形上挖孔,而是用多个矩形将要渲染的部分填充颜色,剩下的部分自然就是透明的:

好使用纯CSS绘制一个中国结并添加动画效果

CSS实现如下:

:root{...--conic:#000090deg,transparent0100%;}.grid{...&:after{...-webkit-mask:conic-gradient(from0degatvar(--width)calc(var(--width)*1.5),var(--conic))00/calc(var(--width)*3)calc(var(--width)*3),conic-gradient(from90degatcalc(var(--width)*2.5)0,var(--conic))00/calc(var(--width)*3)calc(var(--width)*3),conic-gradient(from180degatcalc(var(--width)*1.5)var(--width),var(--conic))00/calc(var(--width)*3)calc(var(--width)*3),conic-gradient(from90degat0calc(var(--width)*2.5),var(--conic))00/calc(var(--width)*3)calc(var(--width)*3);}}

预览效果

好使用纯CSS绘制一个中国结并添加动画效果

目前为止完整代码

: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),transparentvar(--width))00/calc(var(--width)*1.5)calc(var(--width)*1.5);--conic:#000090deg,transparent0100%;}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(from0degatvar(--width)calc(var(--width)*1.5),var(--conic))00/calc(var(--width)*3)calc(var(--width)*3),conic-gradient(from90degatcalc(var(--width)*2.5)0,var(--conic))00/calc(var(--width)*3)calc(var(--width)*3),conic-gradient(from180degatcalc(var(--width)*1.5)var(--width),var(--conic))00/calc(var(--width)*3)calc(var(--width)*3),conic-gradient(from90degat0calc(var(--width)*2.5),var(--conic))00/calc(var(--width)*3)calc(var(--width)*3);}}
<divclass="grid"></div>

没错,这个图形,只用了.grid这一个标签!

但是只有网格还不够,让我们继续。

2. 半圆环

回头看一下参考图:

好使用纯CSS绘制一个中国结并添加动画效果

嗯,环形渐变,那就是radial-gradient了:

<divclass="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(circleat50%100%,transparentcalc(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)),transparentcalc(var(--width)*(0.25+1)));}}

好使用纯CSS绘制一个中国结并添加动画效果

这样就得到了半个环形图,让我们使用定位把它和网格结合看看

/*先给最外层加个相对定位,后面的绝对定位都相对这一层*/.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);}}

好使用纯CSS绘制一个中国结并添加动画效果

对比素材图,发现环形不是直接紧贴在网格上的,而是先延伸了一小段直线,再接的曲线。那我们就给它增个高吧:

.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;}}}

上面使用两个伪类,为半圆环加了两截高度为 0.5--width的增高垫,效果如下图

好使用纯CSS绘制一个中国结并添加动画效果

接着复制16个这样的图形,分别定位到各自的位置上:

<divclass="chinese-knot"><divclass="grid"></div><divclass="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(circleat50%100%,transparentcalc(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)),transparentcalc(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);}}}

就得到了这样的效果

好使用纯CSS绘制一个中国结并添加动画效果

哈哈,很像下水管道~

3. 四分之三圆环

还是先看素材:

好使用纯CSS绘制一个中国结并添加动画效果

嗯,不得不怀疑网易云的 LOGO 的灵感是不是就是中国结。

好使用纯CSS绘制一个中国结并添加动画效果

单个环形已经实现了,两个环也不难吧:

<divclass="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(circleat50%50%,transparentcalc(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)),transparentcalc(var(--width)*(0.5+1)),transparentcalc(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)),transparentcalc(var(--width)*(2+1)));}}}

好使用纯CSS绘制一个中国结并添加动画效果

为什么 <i> 标签里要再套一个标签呢,因为接下来我们要执行 clip-path,还要给圆环增高,而clip-path 会给增高的部分也裁剪掉,所以只能再套一层,让内层的 <b> 自己 clip,增高则使用 <i> 的伪类实现。下面就是将圆环右下角 1/4 裁剪掉并且加一个增高垫的代码:

.ring-big{i{...b{...clip-path:polygon(00,100%0,100%50%,50%50%,50%100%,0100%);}&: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),transparentvar(--width),transparentcalc(var(--width)*1.5));}&:after{transform:rotate(90deg);transform-origin:lefttop;top:calc(var(--width)*3.5);left:calc(var(--width)*3.5+1px);}}}

好使用纯CSS绘制一个中国结并添加动画效果

复制一份并定位:

.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);}}}

好使用纯CSS绘制一个中国结并添加动画效果

到这里,工作的一半就已经完成了~继续

4. 十字结

好使用纯CSS绘制一个中国结并添加动画效果

这个图形,相对于上面几个,已经没什么难度了,五个1×1 的正方形,中间的渐变方向和周围四个垂直。

中间的正方形,用父级本身实现,里面周围四个,用四个子<i>标签实现:

<divclass="cross-node"><divclass="node"><i></i><i></i><i></i><i></i></div><divclass="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);}}}

好使用纯CSS绘制一个中国结并添加动画效果

好使用纯CSS绘制一个中国结并添加动画效果

5. 挂绳

前面我们都是让中国结处于一个斜躺的姿态,写头部和尾部之前,让我们先把它摆正:

.chinese-knot{...transform:rotate(-45deg)translate(calc(var(--width)*4),calc(var(--width)*-4));}

好使用纯CSS绘制一个中国结并添加动画效果

回头看素材图:

好使用纯CSS绘制一个中国结并添加动画效果

先确定一下html结构:

<divclass="header"><i></i><b></b><span></span></div>

i 是上面的吊绳,b 是圆环,span 是衔接处的短绳,带点黄色装饰。为了方便调整定位,我们从下往上实现,先写短绳:

: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(circleat50%,transparentcalc(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)),transparentcalc(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);}}

单独效果

好使用纯CSS绘制一个中国结并添加动画效果

整体效果

好使用纯CSS绘制一个中国结并添加动画效果

6. 流苏

好使用纯CSS绘制一个中国结并添加动画效果

确定html结构:

<divclass="footer"><b></b><b></b><divclass="tassels"><i></i><i></i></div></div>

可以看到,流苏部分,有两个弯曲的 1/8 环,我们用两个b 标签来表示。这个形状依然还是先画一个完整的环,然后裁剪来实现:

.footer{position:absolute;left:0;bottom:0;b{position:absolute;width:calc(var(--width)*15);height:calc(var(--width)*15);background:radial-gradient(circleat50%,transparentcalc(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)),transparentcalc(var(--width)*(6.5+1)));}}

好使用纯CSS绘制一个中国结并添加动画效果

加上裁剪并定位:

.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%);}}}

好使用纯CSS绘制一个中国结并添加动画效果

两个小尾巴就实现了。

最后是流苏。先画一下背景上的垂直细线,这里我们用 repeating-linear-gradient 实现,每隔 2px 画一条 1px 宽的透明度为 0.2 的黑线:

.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,transparent1px,transparent3px)50%50%/3px1px;}}}

好使用纯CSS绘制一个中国结并添加动画效果

再蒙上一层黄色的装饰:

.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(00,100%0,100%10%,010%,015%,100%15%,100%85%,085%,090%,100%90%,100%100%,0100%,00);}}}

好使用纯CSS绘制一个中国结并添加动画效果

上面代码中使用 clip-path 对黄色背景裁剪,露出两条红线,裁剪路径可以用下图表示:

好使用纯CSS绘制一个中国结并添加动画效果

最终效果:

好使用纯CSS绘制一个中国结并添加动画效果

三、加点动画

本来到这里就应该结束了。但是我想让这个中国结有点实际用途,比如加点交互什么的。

红包也是春节的习俗之一,那就加一个拉一下中国结掉落红包雨的特效吧~

1. 拉一下

给中国结在:active状态下加个位移即可实现:

.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:all0.5s;&:active{transform:rotate(-45deg)translate(calc(var(--width)*2),calc(var(--width)*-2));}}

好使用纯CSS绘制一个中国结并添加动画效果

2. 画个红包

先搜索一个红包素材:

好使用纯CSS绘制一个中国结并添加动画效果

观察一下红包结构,深红背景,浅红弧形开口,加一个黄色圆形封口,上面写着一个繁体的开字。

我们可以先确定 html 结构。.rain 作为外层,代表整个红包雨,一个i标签代表一个红包:

<divclass="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:0calc(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:1px1px0rgba(0,0,0,0.1);}}}

好使用纯CSS绘制一个中国结并添加动画效果

使用i标签自身实现红包主体,:before 伪类实现弧形的开口,:after 伪类实现黄色圆形封口,在content中写上字。

一个红包完成了,再复制 9 个:

<divclass="rain"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div>

好使用纯CSS绘制一个中国结并添加动画效果

这样就得到了 10 个固定在顶部,并且整齐排列的红包了。

3. 红包雨动画

下雨嘛,从上往下运动就好了:

.rain{...i{...animation:fall3sease-ininfinite;}}@keyframesfall{0%{transform:translate(0,0);}100%{transform:translate(0,100vh);}}

好使用纯CSS绘制一个中国结并添加动画效果

聪明的你估计已经猜到了这样的结果:谁家的雨是这样齐刷刷的下来的?

那我们就红包的垂直位置错落一点,使用 sassrandom 函数来实现随机:

.rain{...i{...@for$ifrom1through10{&:nth-child(#{$i}){top:random(60)+vh;}}}}

好使用纯CSS绘制一个中国结并添加动画效果

额,效果怎么和想象的不一样。依旧还是齐刷刷下落,只不过是"错落"的齐刷刷。

那我们让每个红包的开始时间也随机不就行了嘛:

.rain{...i{...@for$ifrom1through10{&:nth-child(#{$i}){top:random(60)+vh;animation-delay:random(30)*0.1s;}}}}

好使用纯CSS绘制一个中国结并添加动画效果

嗯,好了一点点。但是有一个问题,屏幕上的雨点,有时候很多,有时候很少,不够均匀。那我们把动画的持续时间也随机会怎么样呢?

.rain{...i{...@for$ifrom1through10{&:nth-child(#{$i}){top:random(60)+vh;animation-delay:random(30)*0.1s;animation-duration:random(10)*0.1s+2s;/*2s~3s之间随机*/}}}}

好使用纯CSS绘制一个中国结并添加动画效果

终于更像雨了~

但是现在雨滴是凭空出现的,很生硬,我们只要把开始的位置挪到负一屏,然后让它下落到正二屏就行了:

.rain{...top:-100vh;}@keyframesfall{0%{transform:translate(0,0);}100%{transform:translate(0,200vh);}}

好使用纯CSS绘制一个中国结并添加动画效果

这样就有了源源不断下落的效果。

4. 拉一下触发红包雨

CSS 不是 JS ,怎么触发点击事件呢?

我们就要运用 CSS 本身的特性了,checkbox 复选框有个选中状态 :checked,而复选框可以用点击切换这个状态,再使用 CSS 的兄弟选择器 element ~ element 即可实现点击添加样式的效果。

样式可以触发了,那如何触发动画呢?

animation 属性添加到元素上后,播放状态默认是 running ,我们需要先把初始播放状态改为 paused (暂停), 然后通过上面的方法,把元素的播放状态改回 running 来实现播放动画的效果:

<inputtype="checkbox"id="switch"><labelclass="chinese-knot"for="switch">...</label><divclass="rain">...</div>
.rain{...i{...animation:fall3sease-ininfinite;/*默认不播放动画*/animation-play-state:paused;}}#switch{visibility:hidden;pointer-events:none;}/*checkbox选中时播放动画*/#switch:checked~.raini{animation-play-state:running;}/*点击时重置动画,否则取消checkbox选中状态,动画会中止并停留在当前位置*/.chinese-knot:active~.raini{animation:none;}

上面的 html 中,我们让.chinese-knotdiv 改为 label 来指向 checkbox,方法是 labelforcheckboxid 设为相同的值。

好使用纯CSS绘制一个中国结并添加动画效果

效果很不错,我们再给红包雨下落时加个背景,以提醒用户当前的状态。并且下红包雨时,调低中国结的透明度,以突出红包的存在感。

<inputtype="checkbox"id="switch"><divclass="bg"></div><labelclass="chinese-knot"for="switch">...</label><divclass="rain">...</div>
.bg{position:absolute;left:0;top:0;height:100vh;width:100vw;background:linear-gradient(0deg,#171a4b,#96367f);opacity:0;transition:all0.5s;}#switch:checked~.bg{opacity:1;}#switch:checked~.chinese-knot{opacity:0.2;&:hover{opacity:0.5;}}

好使用纯CSS绘制一个中国结并添加动画效果

css的基本语法是什么

css的基本语法是:1、css规则由选择器和一条或多条声明两个部分构成;2、选择器通常是需要改变样式的HTML元素;3、每条声明由一个属性和一个值组成;4、属性和属性值被冒号分隔开。

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:好使用纯CSS绘制一个中国结并添加动画效果的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:mysql中with...as的用法是什么下一篇:

4 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18