在CSS中使⽤三⾓函数绘制曲线图形及展⽰动画
最近⼀直在使⽤实现⼀些 CSS 效果。
css-doodle 是⼀个基于 Web-Component 的库。允许我们快速的创建基于 CSS Grid 布局的页⾯,以实现各种 CSS 效果(或许可以称之为 CSS 艺术)。后续⼏篇⽂章可能都会与之有关。
当然,本⽂的主⾓并不是 css-doodle。
CSS本⾝⼀直在快速发展更新,标准也与时俱进,各种新特性层出不穷,为了能够使⽤ CSS 来创造各种布局实现各种形状,除了合理运⽤及搭配各个属性之外,去理解压榨每个属性的每个细节点也是⾮常重要的。
本⽂将介绍⼀种在 CSS 中借助三⾓函数绘制曲线图形的⼩技巧。
理解 box-shadow
⾸先,回顾⼀下box-shadow这个属性。基本属性⽤法就是给元素创造⼀层阴影。
关于阴影的许多细节,可以先看看这篇⽂章:
再简单提⼀下,本⽂会⽤到的关于阴影的第⼀个技巧:
使⽤阴影复制图像/投影图像
当 box-shadow 的第三、第四个参数模糊半径和扩张半径都为 0 的时候,我们可以得到⼀个和元素⼤⼩⼀样的阴影:
1 2 3 4 5 6 7div {
width: 80px;
height: 80px;
border: 1px solid#333;
box-sizing: border-box;
box-shadow: 80px80px00#000; }
得到如下结果:
阴影可以是多重的
第⼆个技巧则是,box-shadow是允许多重阴影的,并且他们的坐标是可以完全掌控的。
是的,我们可以像下⾯这样给⼀个元素定义多重阴影,并且利⽤阴影的第⼀、第⼆个参数控制它相对于元素的坐标:1
2 3 4 5 6 7 8 9 10 11div {
width: 80px;
height: 80px;
border: 1px solid#333;
box-sizing: border-box;
box-shadow:
80px80px00#000,
70px70px00#000,
...
60px60px00#000; }
在阴影坐标中运⽤三⾓函数
继续。接下来,我们尝试在阴影的坐标中引⼊三⾓函数。
为啥是三⾓函数,不是圆的标准⽅程或者椭圆的标准⽅程或者其他图形函数呢?当然也是可以的,只是这⾥借助三⾓函数的cos或sin可以实现直接使⽤CSS 实现起来很困难的曲线。
带着疑问,先继续向下,假设我们要实现这样⼀条曲线:
使⽤ CSS 的话,有什么办法呢?
可能的⼀些办法是clip-path,或者⼀些奇技淫巧,使⽤text-decoration⾥的波浪下划线wavy,或者是使⽤渐变叠加。
当然,还有⼀种办法是本⽂将提到的使⽤box-shadow及三⾓函数。
三⾓函数
咳咳,简单回顾下三⾓函数⾥⾯的 sin、cos 曲线图像变换,还没有全部还给⽼师。
如果我们有⼀个 1x1 的 div,它的多重阴影,能够按照像正弦/余弦函数的图像⼀样进⾏排布,连起来不就是⼀条曲线吗?
如何在 CSS 中使⽤三⾓函数 sin/cos
简单⽽⾔,就是借助,使⽤ Sass 函数模拟实现三⾓函数的 sin()、cos()、tan():
由于展开式是⽆限长的,使⽤ Sass 函数模拟时,不可能得到⼀个⾮常精确的值,但是在⽇常作图下已经完全够⽤了,以下是使⽤的 sin()、cos()、tan():
1
borderbox32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
@return $unitless;
}
@function pi() {
@return    3.14159265359;
}
@function sin($angle) {
$sin: 0;
$angle: rad($angle);
// Iterate a bunch of times.
@for $i from 0through 20{
$sin: $sin + pow(-1, $i) * pow($angle, (2* $i + 1)) / fact(2* $i + 1);
}
@return $sin;
}
@function cos($angle) {
$cos: 0;
$angle: rad($angle);
// Iterate a bunch of times.
@for $i from 0through 20{
$cos: $cos + pow(-1, $i) * pow($angle, 2* $i) / fact(2* $i);
}
@return $cos;
}
@function tan($angle) {
@return sin($angle) / cos($angle);
}
由于上⾯最终计算 sin、cos 泰勒展开的时候,只使⽤了 20 层循环,所以当传⼊的值太⼤的时候,则会产⽣较⼤误差。经测试,传⼊数值在 [-20, 20] 以内,精度还是⾮常⾼的。
⽽以 sin 函数为例,x 取值在 [-π, π] 之间,已经能覆盖所有 sin(x) 的取值范围,所以 [-20, 20] 这个范围是完全够⽤的,我们只需要尽量让传⼊的 x 值落在这个区域范围内即不会产⽣太⼤误差。
好,铺垫了那么多,接下来使⽤上述的 sin 函数试⼀下,假设我们有这样⼀个结构:
1<div></div>
1
2 3 4 5 6div {
width: 1px;
height: 1px;
background: #000;
border-radius: 50%; }
我们再借助 Sass 实现⼀个 50 层的循环,当然其中阴影的 x 坐标使⽤了 sin 函数:1
2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18@function shadowSet($vx, $vy) {
$shadow : 0000#000;
@for $i from 0through 50{
$x: sin($i / 8) * $vx;
$y: $i * $vy;
$shadow: $shadow, #{$x} #{$y} 00rgba(0, 0, 0, 1);
}
@return $shadow;
}
div {
width: 1px;
height: 1px;
background: #000;
border-radius: 50%;
box-shadow: shadowSet(4px, 1px);
}
实际得到的图像如下:
控制颜⾊
再进⼀步,我们可以借助 Sass 的各种颜⾊函数,实现颜⾊的变化:1
OK,看看这次的效果:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。