当前位置: 首页 > 科技观察

使用CSS制作波浪效果的妙招

时间:2023-03-14 00:05:27 科技观察

之前介绍过几种使用纯CSS实现波浪效果的方法,相关的文章有两篇:纯CSS实现波浪效果![1]乔用CSS实现炫酷的充电动画[2]本文将介绍另一种用CSS实现的波浪效果,思路很有意思。我们先从定积分开始,实现弯曲三角形的面积。在进入正题之前,我们先来看看这个。在高等数学中,我们可以用定积分求二次函数曲线边的面积。我们可以把曲线下的面积分成n个细长的长方形。当n无限趋近于无穷大时,所有矩形的面积都等于曲线边图形的面积。两张简单的示意图,取自为什么定积分可以用来计算面积?[3]:当n无限趋近于无穷大时,所有矩形的面积等于曲线边缘图形的面积:图片利用这个思路,我们也可以在CSS中用Multiplediv模拟一个曲线边缘,即一个波浪线。Step1.将图形分割成多个部分首先,我们可以定义一个父容器,父容器下有12个子div:

通过flex布局,简单布局得到这样一个图形,每个子元素等高:.g-container{width:200px;height:200px;border:2pxsolid#fff;display:flex;align-items:flex-end;}.g-item{flex-grow:1;height:60px;background-color:#fff;}效果如下:Step2.让每个子元素运行不同负延迟的高度变换动画Up,通过改变高度每个子元素:.g-item{flex-grow:1;height:60px;background-color:#000;animation:heightChange1sinfiniteease-in-outalternate;}@keyframesheightChange{from{height:60px;}to{height:90px;}}效果如下:接下来只需要设置每个的动画顺序childelement一个不同时间的负延迟就足以得到一个初步的波浪效果。这里为了减少工作量,我们使用SASS实现:$count:12;$speed:1s;.g-item{--f:#{$speed/-12};flex-grow:1;height:60px;background-color:#000;animation:heightChange$speedinfiniteease-in-outalternate;}@for$ifrom0to$count{.g-item:nth-child(#{$i+1}){animation-delay:calc(var(--f)*#{$i});}}@keyframesheightChange{from{height:60px;}to{height:90px;}}这样我们就得到了初步的波浪效果:Step3.抗锯齿正如你所看到的,上面提到的波浪动画存在一定的锯齿,接下来我们要做的就是尽可能的消除这些锯齿。方法一:增加div个数一开始是基于利用定积分求曲线边缘图形面积的思路。我们只需要尽可能地增加sub-div的数量。当div的数量无限大时,锯齿就会消失。我们可以试试把上面的12个sub-div换成120个。120个div一个一个写,太费力了。这里我们使用Pug[4]模板引擎:div.g-container-for(vari=0;i<120;i++)div.g-itemCSS代码,只需要改变动画延迟时间,和120个sub-divs的负延时控制在1s以内://12--120$count:120;$speed:1s;.g-item{//注意,只是这里改了--f:#{$speed/-120};flex-grow:1;height:60px;background-color:#000;animation:heightChange$speedinfiniteease-in-outalternate;}@for$ifrom0to$count{.g-item:nth-child(#{$i+1}){animation-delay:calc(var(--f)*#{$i});}}这样可以得到更平滑的曲线:方法二:通过transform模拟弧度:skew()当然,在实际情况下,用那么多div太浪费了,那么有没有别的办法呢?当div数量比较少的时候,能不能尽量消除锯齿呢?这里,我们可以尝试在运动变换过程中给子元素添加不同的transform:skewY()来模拟弧度。然后修改代码,我们降低div的个数,给每个子div添加一个transform:skewY()的动画效果:div.g-container-for(vari=0;i<24;i++)div。g-item完整的CSS代码如下:$count:24;$speed:1s;.g-item{//注意,只是这里变了--f:#{$speed/-24};flex-增长:1;高度:60px;背景颜色:#000;动画:heightChange$speedinfiniteease-in-outalternate,skewChange$speedinfiniteease-in-outalternate;}@for$ifrom0to$count{.g-item:nth-child(#{$i+1}){动画延迟:calc(var(--f)*#{$i}),calc(var(--f)*#{$i}-#{$speed/2});}}@keyframesheightChange{from{height:var(--h);}to{height:calc(var(--h)+30px);}}@keyframeskewChange{from{transform:skewY(20deg);}to{transform:skewY(-20deg);}}为了方便理解,我们先来看一下在高度变换动画一致的情况下,sub-div用skewY()的变换是如何添加的:可以看到每次变换都是明显的突出的锯齿,叠加延迟的高度变换,可以消除大部分的锯齿效果:至此,我们又得到了另一种div数量适中的抗锯齿方法!以上所有效果的完整代码,可以点这里:CodePen--PureCSSWaveEffects[5]混合使用最后我们可以通过调整几个变量参数来组合几种不同的波浪效果,得到一些组合效果,也很不错.类似于这个:CodePen--PureCSSWaveEffects2[6]基于此,我想到了我们公司(Shopee)的母公司--SeaGroup的LOGO,看起来是这样的:使用本文中的解决方案来实现动态LOGO动画:CodePenDemo--PureCSSWave-SeaGroupLogo[7]效果会更好。当然,如果增加到一定程度,卡顿在所难免,锯齿感也无法完全消除。这才是最致命或者说是真正可以发挥作用的地方。当然,这篇文章的目的更多的是为了开阔思路,探讨这种方法的优缺点,实现动画的整个过程,动画负延迟时间的应用,都具有一定的参考和学习意义。CSS还是很有意思的~🤣最后,本文到此结束,希望对大家有所帮助:)参考[1]纯CSS实现波浪效果!:https://github.com/chokcoco/iCSS/issues/22[2]使用CSS实现酷炫的充电动画:https://github.com/chokcoco/iCSS/issues/75[3]为什么定积分可以计算面积?:https://www.zhihu.com/question/21439225[4]Pug:https://github.com/pugjs/pug[5]CodePen——PureCSS波浪效果:https://codepen.io/Chokcoco/pen/XWpxQBd[6]CodePen——PureCSSWaveEffects2:https://codepen.io/Chokcoco/pen/yLgQgLo[7]CodePenDemo--PureCSSWave-SeaGroupLogo:https://codepen.io/Chokcoco/pen/zYZrmvb[8]Github--iCSS:https://github.com/chokcoco/iCSS