一种巧妙的使用 CSS 制作波浪效果的思路

简介: 一种巧妙的使用 CSS 制作波浪效果的思路

在之前,我介绍过几种使用纯 CSS 实现波浪效果的方式,关于它们有两篇相关的文章:



本文将会再介绍另外一种使用 CSS 实现的波浪效果,思路非常有意思。


从定积分实现曲边三角形面积说起



在进入主题之前,先看看这个,在高等数学中,我们可以通过定积分求二次函数曲边图形面积。


我们可以将曲线下的面积分割成 n 个的细高的矩形,当 n 无限趋近于无穷时,所有矩形的面积就等于曲边图形的面积。


两张简单的示意图,图取自为什么定积分可以求面积?

ef703171dfd7431886f3921e3753c263_tplv-k3u1fbpfcp-zoom-1.png



当 n 无限趋近于无穷时,所有矩形的面积就等于曲边图形的面积:


be4b738cd93d404a8ad05b6518ddfd3a_tplv-k3u1fbpfcp-zoom-1.png



利用这个思路,我们也可以通过多个 div 在 CSS 中模拟出一条曲边,也就是波浪线。


Step 1. 将图形切割为多份


首先,我们可以定义一个父容器,父容器下有 12 个子 div:


<div class="g-container">
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
</div>

通过 flex 布局,简单布局一下,得到这样一个图形,每个子元素等高:


.g-container {
    width: 200px;
    height: 200px;
    border: 2px solid #fff;
    display: flex;
    align-items: flex-end;
}
.g-item {
    flex-grow: 1;
    height: 60px;
    background-color: #fff;
}


效果如下:


5a631f7b4027418d935c4facf08fb80d_tplv-k3u1fbpfcp-zoom-1.png


Step 2. 让每个子元素以不同负延迟运行高度变换动画


接下来,简单改造下,我们需要让这个图动起来,通过改变每个子元素的高度实现:


.g-item {
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: heightChange 1s infinite ease-in-out alternate;
}
@keyframes heightChange {
    from {
        height: 60px;
    }
    to {
        height: 90px;
    }
}


效果如下:

8d97aea9bc8a4f3b97c8cf79ee956433_tplv-k3u1fbpfcp-zoom-1.gif

接下来,只需要,让每个子元素的动画顺序设定一个不同时间的负延迟即可,就可以得到一个初步的波浪效果,这里为了减少工作量,我们借助 SASS 实现:


$count: 12;
$speed: 1s;
.g-item {
    --f: #{$speed / -12};
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: heightChange $speed infinite ease-in-out alternate;
}
@for $i from 0 to $count {
    .g-item:nth-child(#{$i + 1}) {
        animation-delay: calc(var(--f) * #{$i});
    }
}
@keyframes heightChange {
    from {
        height: 60px;
    }
    to {
        height: 90px;
    }
}


这样,我们就得到了一个初步的波浪效果:


eb0202e856d24ae9b4ecc24f8a0d7467_tplv-k3u1fbpfcp-zoom-1.gif


Step 3. 消除锯齿



可以看到,上述的波浪动画是存在一定的锯齿的,接下来我们要做的就是尽可能的消除掉这些锯齿。


法一:增加 div 的数量


按照一开始使用定积分求曲边图形面积的思想,我们只需要尽可能增加子 div 的数量即可,当 div 的数量无穷多的时候,锯齿也就会消失不见。


我们可以尝试将上述的 12 个子 div,替换成 120 个试下,一个一个写 120 个 div 太费力了,我们这里借助 Pug 模板引擎:


div.g-container
 -for(var i=0; i<120; i++)
    div.g-item

对于 CSS 代码,只需要改动动画延迟的时间即可,120 个子 div 的负延迟都控制在 1s 内:


// 12 -- 120
$count: 120;
$speed: 1s;
.g-item {
    // 注意,只有这里发生了变化
    --f: #{$speed / -120};
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: heightChange $speed infinite ease-in-out alternate;
}
@for $i from 0 to $count {
    .g-item:nth-child(#{$i + 1}) {
        animation-delay: calc(var(--f) * #{$i});
    }
}


这样,我们就可以得到一条比较光滑的曲线啦:

c314d074517c4c8786a16e3f9058e5b0_tplv-k3u1fbpfcp-zoom-1.gif



法二:通过 transform: skew() 模拟弧度


当然,实际情况,使用那么多个 div 实在是太浪费了,那么有没有其它方法在 div 数量比较少的情况下,也能够尽可能的消除锯齿呢?


这里,我们可以尝试给子元素在运动变换的过程中添加不同的 transform: skewY() 去模拟弧度。


再改造下代码,我们将 div 的数量调低,并且给每个子 div 再添加一个 transform: skewY() 的动画效果:

div.g-container
 -for(var i=0; i<24; i++)
    div.g-item

完整的 CSS 代码如下:


$count: 24;
$speed: 1s;
.g-item {
    // 注意,只有这里发生了变化
    --f: #{$speed / -24};
    flex-grow: 1;
    height: 60px;
    background-color: #000;
    animation: 
        heightChange $speed infinite ease-in-out alternate,
        skewChange $speed infinite ease-in-out alternate;
}
@for $i from 0 to $count {
    .g-item:nth-child(#{$i + 1}) {
        animation-delay: 
            calc(var(--f) * #{$i}), 
            calc(var(--f) * #{$i} - #{$speed / 2});
    }
}
@keyframes heightChange {
    from {
        height: var(--h);
    }
    to {
        height: calc(var(--h) + 30px);
    }
}
@keyframes skewChange {
    from {
        transform: skewY(20deg);
    }
    to {
        transform: skewY(-20deg);
    }
}


为了方便理解,首先看看,高度变换动画一致的情况下,子 div 的添加了 skewY() 的变换是如何的:


598c29112be24809a0f42a39d9a3a5e8_tplv-k3u1fbpfcp-zoom-1.gif


能看到每次变换是有明显的突起的锯齿的,叠加上延迟的高度变换,就能够很好的消除大部分的锯齿效果:


bbeef5cc9bbe411cb1da92501f445aec_tplv-k3u1fbpfcp-zoom-1.gif

至此,我们就得到了另外一种 div 数量适中的消除锯齿的方法!上述所有效果的完整代码,你可以戳这里:


CodePen -- PureCSS Wave Effects


混合使用



最后,我们可以通过调整几个变量参数,将几个不同的波浪效果组合在一起,得到一些组合效果,也很不错。


类似这样:

18d039d86b064d37a856f5aacaf39ce0_tplv-k3u1fbpfcp-zoom-1.gif

CodePen -- PureCSS Wave Effects 2


基于此,我联想到我们公司(Shopee)的母公司 -- Sea Group 的 LOGO,它长得如下:

ac96676beb744568af9f40dd8a03f4e3_tplv-k3u1fbpfcp-zoom-1.png


利用本文的方案,给它实现一个动态的 LOGO 动画:

62bd78459b2b41ac9ea695f6b9b76485_tplv-k3u1fbpfcp-zoom-1.gif


CodePen Demo -- PureCSS Wave - Sea Group Logo


缺点



该方案的缺点还是很明显的:


  • 首先是废 div,需要比较多的 div 来实现效果,而且 div 越多,效果会越好,当然增加到一定程度,卡顿是不可避免的
  • 锯齿无法完全消除,这个是最致命或者说影响它真正能够有用武之地的地方吧


当然,本文的目的重点更多的是开拓一下思维,探讨一下这种方式的优劣,实现动画的整个过程,动画负延迟时间的运用,都是有一些参考学习意义的。CSS 还是非常有趣的~ 🤣

目录
相关文章
|
4月前
|
前端开发
css 鼠标悬浮时,下划线变成会动的波浪线
css 鼠标悬浮时,下划线变成会动的波浪线
40 1
|
4月前
|
前端开发
CSS特效-超链接动感波浪线
CSS特效-超链接动感波浪线
27 0
|
6月前
|
前端开发
CSS圆角大杀器,使用滤镜构建圆角及波浪效果
CSS圆角大杀器,使用滤镜构建圆角及波浪效果
71 0
|
前端开发
CSS:实现 hover 时文字波浪式变色效果
CSS:实现 hover 时文字波浪式变色效果
|
前端开发
实训-利用HTML+CSS制作某米官网首页(二)
实训-利用HTML+CSS制作某米官网首页
244 0
实训-利用HTML+CSS制作某米官网首页(二)
|
前端开发
实训-利用HTML+CSS制作某米官网首页(一)
实训-利用HTML+CSS制作某米官网首页
325 0
实训-利用HTML+CSS制作某米官网首页(一)
|
存储 移动开发 前端开发
零基础学网页开发入门(制作博客案例)适应手机端div+css+js的综合介绍
零基础学网页开发入门(制作博客案例)适应手机端div+css+js的综合介绍
132 0
零基础学网页开发入门(制作博客案例)适应手机端div+css+js的综合介绍
|
人工智能 JavaScript 前端开发
使用 HTML、CSS 和 JS 制作一个中国象棋
这是一个简单的 JavaScript 项目,中国象棋人机对战,文末有完整源码免费下载地址,祝大家玩得开心,学得轻松。
384 2
使用 HTML、CSS 和 JS 制作一个中国象棋
|
前端开发 JavaScript 程序员
基于CSS的3D旋转画册的制作
这是一种使用CSS做出来的旋转效果,可用于宣传海报
基于CSS的3D旋转画册的制作
|
前端开发
CSS 奇技淫巧 | 巧妙实现文字二次加粗再加边框
CSS 奇技淫巧 | 巧妙实现文字二次加粗再加边框
344 0
CSS 奇技淫巧 | 巧妙实现文字二次加粗再加边框

热门文章

最新文章

下一篇
无影云桌面