• 售前

  • 售后

热门帖子
入门百科

怎样在CSS中绘制曲线图形及展示动画

[复制链接]
Jacqueline季 显示全部楼层 发表于 2021-8-16 11:40:28 |阅读模式 打印 上一主题 下一主题
目次


  • 理解 box-shadow

    • 使用阴影复制图像/投影图像

  • 在阴影坐标中运用三角函数

    • 三角函数
    • 如何在 CSS 中使用三角函数 sin/cos
    • 控制颜色及初始方向
    • 控制颜色

  • 在 css-doodle 中使用
  • 总结

理解 box-shadow

起首,回顾一下box-shadow这个属性。根本属性用法就是给元素创造一层阴影。
再简朴提一下,本文会用到的关于阴影的第一个本事:

使用阴影复制图像/投影图像

当 box-shadow 的第三、第四个参数含糊半径和扩张半径都为 0 的时间,我们可以得到一个和元素大小一样的阴影:
  1. div {
  2.     width: 80px;
  3.     height: 80px;
  4.     border: 1px solid #333;
  5.     box-sizing: border-box;
  6.     box-shadow: 80px 80px 0 0 #000;
  7. }
复制代码
得到如下结果:

阴影可以是多重的
第二个本事则是,box-shadow是答应多重阴影的,而且他们的坐标是可以完全掌控的。
是的,我们可以像下面如许给一个元素界说多重阴影,而且利用阴影的第一、第二个参数控制它相对于元素的坐标:
  1. div {
  2.     width: 80px;
  3.     height: 80px;
  4.     border: 1px solid #333;
  5.     box-sizing: border-box;
  6.     box-shadow:
  7.         80px 80px 0 0 #000,
  8.         70px 70px 0 0 #000,
  9.         ...
  10.         60px 60px 0 0 #000;
  11. }
复制代码
在阴影坐标中运用三角函数

继续。接下来,我们实验在阴影的坐标中引入三角函数。
为啥是三角函数,不是圆的尺度方程大概椭圆的尺度方程大概其他图形函数呢?固然也是可以的,只是这里借助三角函数的cos或sin可以实现直接使用 CSS 实现起来很困难的曲线。
带着疑问,先继续向下,假设我们要实现如许一条曲线:

使用 CSS 的话,有什么办法呢?
可能的一些办法是clip-path,大概一些奇技淫巧,使用text-decoration里的波浪下划线wavy,大概是使用渐变叠加。
固然,还有一种办法是本文将提到的使用box-shadow及 三角函数。

三角函数

咳咳,简朴回顾下三角函数内里的 sin、cos 曲线图像变更,还没有全部还给老师。

如果我们有一个 1x1 的 div,它的多重阴影,可以或许按照像正弦/余弦函数的图像一样举行排布,连起来不就是一条曲线吗?

如何在 CSS 中使用三角函数 sin/cos

想法不错,但是 CSS 本身并没有提供三角函数。这里,我们须要借助 Sass 来在 CSS 中实现简朴的三角函数。
还好,已经有前人帮忙把这个工作做完了:
       
  • trigonometry in sass   
  • 在Sass中实现三角函数计算
简朴而言,就是借助三角函数的泰勒展开式,使用 Sass 函数模仿实现三角函数的 sin()、cos()、tan():

由于展开式是无限长的,使用 Sass 函数模仿时,不可能得到一个非常准确的值,但是在日常作图下已经完全够用了,以下是使用 Sass 函数模仿实现三角函数的 sin()、cos()、tan():
  1. @function fact($number) {
  2.     $value: 1;
  3.     @if $number>0 {
  4.         @for $i from 1 through $number {
  5.             $value: $value * $i;
  6.         }
  7.     }
  8.     @return $value;
  9. }
  10. @function pow($number, $exp) {
  11.     $value: 1;
  12.     @if $exp>0 {
  13.         @for $i from 1 through $exp {
  14.             $value: $value * $number;
  15.         }
  16.     }
  17.     @else if $exp < 0 {
  18.         @for $i from 1 through -$exp {
  19.             $value: $value / $number;
  20.         }
  21.     }
  22.     @return $value;
  23. }
  24. @function rad($angle) {
  25.     $unit: unit($angle);
  26.     $unitless: $angle / ($angle * 0 + 1);
  27.     @if $unit==deg {
  28.         $unitless: $unitless / 180 * pi();
  29.     }
  30.     @return $unitless;
  31. }
  32. @function pi() {
  33.     @return 3.14159265359;
  34. }
  35. @function sin($angle) {
  36.     $sin: 0;
  37.     $angle: rad($angle);
  38.     // Iterate a bunch of times.
  39.     @for $i from 0 through 20 {
  40.         $sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
  41.     }
  42.     @return $sin;
  43. }
  44. @function cos($angle) {
  45.     $cos: 0;
  46.     $angle: rad($angle);
  47.     // Iterate a bunch of times.
  48.     @for $i from 0 through 20 {
  49.         $cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i);
  50.     }
  51.     @return $cos;
  52. }
  53. @function tan($angle) {
  54.     @return sin($angle) / cos($angle);
  55. }
复制代码
由于上面终极计算 sin、cos 泰勒展开的时间,只使用了 20 层循环,以是当传入的值太大的时间,则会产生较大偏差。经测试,传入数值在 [-20, 20] 以内,精度还黑白常高的。
而以 sin 函数为例,x 取值在 [-π, π] 之间,已经能覆盖所有 sin(x) 的取值范围,以是 [-20, 20] 这个范围是完全够用的,我们只须要只管让传入的 x 值落在这个区域范围内即不会产生太大偏差。
好,铺垫了那么多,接下来使用上述的 sin 函数试一下,假设我们有如许一个结构:
  1. div {
  2.     width: 1px;
  3.     height: 1px;
  4.     background: #000;
  5.     border-radius: 50%;
  6. }
复制代码
我们再借助 Sass 实现一个 50 层的循环,固然此中阴影的 x 坐标使用了 sin 函数:
  1. @function shadowSet($vx, $vy) {
  2.     $shadow : 0 0 0 0 #000;
  3.      
  4.     @for $i from 0 through 50 {
  5.         $x: sin($i / 8) * $vx;
  6.         $y: $i * $vy;
  7.          
  8.         $shadow: $shadow, #{$x} #{$y} 0 0 rgba(0, 0, 0, 1);
  9.     }
  10.      
  11.     @return $shadow;
  12. }
  13. div {
  14.     width: 1px;
  15.     height: 1px;
  16.     background: #000;
  17.     border-radius: 50%;
  18.     box-shadow: shadowSet(4px, 1px);
  19. }
复制代码
上面sin($i / 8),这里除以 8 是为了让整个sin(x) 传入的作用域的取值范围为 [0, 6.25],当而 sin(x) 的作用域为 [0,2π] 时刚好可以画一条完整的单次曲线。这个 8 是可以根据循环的次数差别而举行调整的。
现实,我们得到的box-shadow如下:
  1. {
  2.     box-shadow:
  3.     0 0 0 0 black, 0.4986989335px 1px 0 0 black, 0.989615837px 2px 0 0 black,
  4.     1.4650901163px 3px 0 0 black, 1.9177021544px 4px 0 0 black, 2.3403890918px 5px 0 0 black,
  5.     2.7265550401px 6px 0 0 black, 3.0701740089px 7px 0 0 black, 3.3658839392px 8px 0 0 black,
  6.     3.6090703764px 9px 0 0 black, 3.7959384774px 10px 0 0 black, 3.9235722281px 11px 0 0 black,
  7.     3.9899799464px 12px 0 0 black, 3.9941253622px 13px 0 0 black, 3.9359437875px 14px 0 0 black,
  8.     3.8163431264px 15px 0 0 black, 3.6371897073px 16px 0 0 black, 3.4012791593px 17px 0 0 black,
  9.     3.1122927876px 18px 0 0 black, 2.7747401278px 19px 0 0 black, 2.3938885764px 20px 0 0 black,
  10.     1.9756811944px 21px 0 0 black, 1.5266439682px 22px 0 0 black, 1.0537839735px 23px 0 0 black,
  11.     0.5644800322px 24px 0 0 black, 0.0663675689px 25px 0 0 black, -0.4327805381px 26px 0 0 black,
  12.     -0.9251752496px 27px 0 0 black, -1.4031329108px 28px 0 0 black, -1.8591951521px 29px 0 0 black,
  13.     -2.286245275px 30px 0 0 black, -2.677619305px 31px 0 0 black, -3.0272099812px 32px 0 0 black,
  14.     -3.3295620582px 33px 0 0 black, -3.5799574329px 34px 0 0 black, -3.7744887692px 35px 0 0 black,
  15.     -3.9101204707px 36px 0 0 black, -3.9847360499px 37px 0 0 black, -3.9971711559px 38px 0 0 black,
  16.     -3.9472317429px 39px 0 0 black, -3.8356970987px 40px 0 0 black, -3.6643076841px 41px 0 0 black,
  17.     -3.4357379737px 42px 0 0 black, -3.1535547213px 43px 0 0 black, -2.8221613023px 44px 0 0 black,
  18.     -2.446729px 45px 0 0 black, -2.03311631px 46px 0 0 black, -1.58777752px 47px 0 0 black,
  19.     -1.1176619928px 48px 0 0 black, -0.630105724px 49px 0 0 black, -0.1327168662px 50px 0 0 black;
  20. }
复制代码
现实得到的图像如下:


控制颜色及初始方向

看看上面 Sass 实现的这个方法@function shadowSet($vx, $vy),此中$vx,$vy用于控制图像的振幅及疏松水平,我们再添加一个控制初始方向的$direction,控制阴影层数的 $count, 控制颜色的 $color:
  1. @function shadowSet($vx, $vy, $direction, $count, $color) {
  2.     $shadow : 0 0 0 0 $color;
  3.      
  4.     @for $i from 0 through $count {
  5.         $x: sin($i / 8) * $vx * $direction;
  6.         $y: $i * $vy;
  7.          
  8.         $shadow: $shadow, #{$x} #{$y} 0 0 $color;
  9.     }
  10.      
  11.     @return $shadow;
  12. }
  13. .line {
  14.     width: 1px;
  15.     height: 1px;
  16.     margin: 10vh auto;
  17.     background: #000;
  18.     border-radius: 50%;
  19.     box-shadow: shadowSet(4px, 1px, 1, 50, #000);
  20. }
  21. .reverseline {
  22.     width: 1px;
  23.     height: 1px;
  24.     margin: 10vh auto;
  25.     background: #000;
  26.     border-radius: 50%;
  27.     box-shadow: shadowSet(8px, 2px, -1, 100, red);
  28. }
复制代码


控制颜色

再进一步,我们可以借助 Sass 的各种颜色函数,实现颜色的变革:
  1. @function shadowSetColor($vx, $vy, $direction, $count, $color) {
  2.     $shadow : 0 0 0 0 $color;
  3.      
  4.     @for $i from 0 through $count {
  5.          
  6.         $color: lighten($color, .5);
  7.          
  8.         $x: sin($i / 8) * $vx * $direction;
  9.         $y: $i * $vy;
  10.          
  11.         $shadow: $shadow, #{$x} #{$y} 0 0 $color;
  12.     }
  13.      
  14.     @return $shadow;
  15. }
  16. .colorline {
  17.     width: 5px;
  18.     height: 5px;
  19.     margin: 10vh auto;
  20.     background: green;
  21.     border-radius: 50%;
  22.     box-shadow: shadowSetColor(8px, 2px, -1, 100, green);
  23. }
复制代码
上面,借助了lighten这个函数,通过改变颜色的亮度值,让颜色变亮,创建一个新的颜色。
固然,Sass 中还有许多其他颜色函数:
       
  • adjust-hue($color,$degrees):通过改变一个颜色的色相值,创建一个新的颜色;   
  • lighten($color,$amount):通过改变颜色的亮度值,让颜色变亮,创建一个新的颜色;   
  • darken($color,$amount):通过改变颜色的亮度值,让颜色变暗,创建一个新的颜色;   
  • saturate($color,$amount):通过改变颜色的饱和度值,让颜色更饱和,从而创建一个新的颜色   
  • desaturate($color,$amount):通过改变颜色的饱和度值,让颜色更少的饱和,从而创建出一个新的颜色;
OK,看看这次的效果:
  1. @function fact($number) {
  2.     $value: 1;
  3.     @if $number>0 {
  4.         @for $i from 1 through $number {
  5.             $value: $value * $i;
  6.         }
  7.     }
  8.     @return $value;
  9. }
复制代码
在 css-doodle 中使用

OK,前面所有的铺垫都是为了在现实的一些创意想法中去使用它。
在 css-doodle 中,由于是利用 Web Component 特性。在须要三角函数的时间,可以直接使用 JavaScript 提供的 Math 函数,会更加的方便。
Web Components 是一套差别的 Web 技能,答应您创建可重用的定制元素(它们的功能封装在您的代码之外)而且在您的web应用中使用它们。
袁川老师,也就是 css-doodle 库的作者,在他的 Codepen 首页配景板中,使用的就是使用上述本事实现的一副纯 CSS 画作:
  1. html, body {  
  2.   height: 100%;  
  3.   margin: 0;
  4.   display: flex;
  5.   align-items: center;
  6.   justify-content: center;
  7.   background: #000;
  8. }
复制代码
  1. <style>
  2.   css-doodle {
  3.     --color: @p(#010059, #52437b, #ff7a8a, #fcf594)@p([2-9a-d])@lp();
  4.     --rule: (
  5.       :doodle {
  6.         @grid: 8 / 120vmin 80vmin;
  7.         max-width: 100vw;
  8.         background: linear-gradient(#ff7a8a, #fcf594);
  9.         filter: hue-rotate(-22deg);
  10.         overflow: hidden;
  11.       }
  12.       @size: @r(4vmin, 15vmin);
  13.       mix-blend-mode: multiply;
  14.       transform: translate(@m2(@r(-80%, 100%)));
  15.       border-radius: 50%;
  16.       --n: @p(-1, 1);
  17.       --c: var(--color);
  18.       box-shadow: @m100(
  19.         calc(@sin(@n() / 10) * 1.8vmin * @var(--n))
  20.         calc(@n() * 1vmin) 0
  21.         @var(--c)
  22.       );
  23.       background: @m(@p(0, @ri(500)), (
  24.         radial-gradient(var(--color) 50%, transparent 0)
  25.         @r(100%) @r(100%) / @r(1px, 3px) @lr()
  26.         no-repeat
  27.       ));
  28.       background-color: var(--color);
  29.     );
  30.   }   
  31. </style>
  32. <css-doodle use="var(--rule)" click-to-update></css-doodle>
复制代码
我也实验使用这个本事,做了一副


总结

有几点,有须要提一下的。
1、为什么肯定要使用box-shadow,直接堆叠 div 不可么?
可以,使用多重box-shadow只是由于如许可以更省标签,一个 div 搞定。更甚,乐意折腾,使用多重渐变也是可以的。
2、上述两个 Demo 都是纯 CSS 画出来的吗?
是的。固然借助了 css-doodle 库,但是本质都是 CSS 代码,只是这个库封装好了许多拿来即用的函数。css-doodle
3、有什么用?
额,有没有用是一个哲学标题。至少我以为照旧挺有意思的。
以上就是如何在CSS中绘制曲线图形及展示动画的详细内容,更多关于在CSS中绘制曲线图形及展示动画的资料请关注脚本之家别的相干文章!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作