现代 CSS 解决方案:CSS 原生支持的三角函数
Posted ChokCoco
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了现代 CSS 解决方案:CSS 原生支持的三角函数相关的知识,希望对你有一定的参考价值。
在 CSS 中,存在许多数学函数,这些函数能够通过简单的计算操作来生成某些属性值,例如 :
- calc():用于计算任意长度、百分比或数值型数据,并将其作为 CSS 属性值。
- min() 和 max():用于比较一组数值中的最大值或最小值,也可以与任意长度、百分比或数值型数据一同使用。
- clamp():用于将属性值限制在一个范围内,支持三个参数:最小值、推荐值和最大值。
在现代 CSS 解决方案:CSS 数学函数一文中,我们详细介绍了
- calc()
- min()
- max()
- clamp()
四个数学函数。
而本文,将给大家介绍一下最近各大浏览器也逐渐开始原生支持的三角函数:
- sin()
- cos()
- tan()
CSS 三角函数语法介绍
首先,我们来看看 CSS 三角函数的使用方式:
.box
/* 设置元素的宽度为 sin(30deg) 的值 */
width: calc(sin(30deg) * 100px);
/* 设置元素的高度为 cos(45deg) 的值 */
height: calc(cos(45deg) * 100%);
/* 设置元素的透明度为 tan(60deg) 的值 */
opacity: calc(tan(60deg));
上述代码中,我们使用了 calc() 函数进行了计算,然后通过 sin()、cos() 和 tan() 函数对计算结果进行了进一步的处理,从而实现了不同的效果。
需要注意的是,三角函数在 CSS3 中仅对弧度(radian)单位进行支持。如果想要在开发中使用三角函数,可以借助转换函数 deg() 和 rad() 将角度(degree)和弧度进行转换。
CSS3 的这些函数使得开发者可以更加方便处理一些复杂的数学问题,增强了 CSS 的表现力。
三角函数的运动轨迹
三角函数的运用,更多的是在动画当中。以正弦、余弦函数为例,其图形如下:
我们通过一个简单的例子,还原三角函数的图形,以此来感受三角函数的作用。首先,我们实现一个黑色圆球:
<div class=\'g-single\'></div>
.g-single
width: 20px;
height: 20px;
background: #000;
border-radius: 50%;
效果如下:
我们可以通过 transfrom
,借助 CSS @property 属性,来构造一个三角函数的使用场景:
.g-single
width: 20px;
height: 20px;
background: #000;
border-radius: 50%;
animation: move 5s infinite ease-in-out;
transform: translate(
calc(var(--dis) - 40vw),
calc(5 * sin(var(--angle)) * 1em)
);
@keyframes move
0%
--dis: 0px;
--angle: 0deg;
100%
--dis: 80vw;
--angle: 1080deg;
上述的核心在于这一段代码 -- transform: translate(calc(var(--dis) - 40vw), calc(5 * sin(var(--angle)) * 1em))
,内部使用了两个 CSS @property 变量:
- x 轴方向是
0px
到80vw
的水平位移动画 - y 轴方向是
5 * sin(0deg) * 1em
到5 * sin(1080deg) * 1em
的竖直动画
通过动画,动态的修改这两个变量的值,我们就可以得到一个三角函数曲线动画图形:
如果我们,设定多个一模一样的小球,同一个运动轨迹,设定不同的 animation-delay
,效果会上怎么样呢?
<ul class="g-multi">
<li> </li>
// ... 一共 80 个 li
<li> </li>
</ui>
li
animation: move 5s infinite ease-in-out;
transform: translate(
calc(var(--dis) - 40vw),
calc(5 * sin(var(--angle)) * 1em);
@for $i from 1 to $count
li:nth-child(#$i)
animation-delay: #$i * 5 / $count * -1s;
@keyframes move
0%
--dis: 0px;
--angle: 0deg;
100%
--dis: 80vw;
--angle: 1080deg;
这样,就得到了这么一个动画,非常的类似三角函数动画的曲线:
完整的代码,你可以戳这里:CodePen Demo -- CSS Cos/Sin Math function
快速实现圆弧轨迹动画
在之前,我们想实现一个圆弧动画,如下所示,还是稍微有点点麻烦的:
有了三角函数之后,类似的动画,可以节省部分代码实现:
<div></div>
@property --angle
syntax: \'<angle>\';
inherits: false;
initial-value: 0deg;
.g-single
background: #000;
width: 20px;
height: 20px;
border-radius: 50%;
animation: move 3s infinite linear;
transform: translate(
calc(sin(var(--angle)) * 10vmin),
calc(cos(var(--angle)) * 10vmin)
);
@keyframes move
0%
--angle: 0deg;
100%
--angle: 360deg;
核心就在于 transform: translate(calc(sin(var(--angle)) * 10vmin), calc(cos(var(--angle)) * 10vmin));
,简化一下这段代码,表达式为:
transform: translate(sinX, conX)
,其中 X 为角度变化
如此,我们只需要动态设置 X 从 0deg
到 360deg
的变化即可,就可以得到一个圆形动画效果:
完整的代码,你可以戳这里:CodePen Demo -- CSS Cos/Sin Math function - arc animation
基于这个技巧,我们可以尝试实现一个旋转的 Loading 动画,代码也非常简单:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
@property --angle
syntax: \'<angle>\';
inherits: false;
initial-value: 0deg;
ul
position: relative;
li
position: absolute;
inset: 0;
border-radius: 50%;
animation: move 3s infinite ease-in-out;
transform: translate(
calc(sin(var(--angle)) * 60px),
calc(cos(var(--angle)) * 60px)
);
@for $i from 1 to 11
li:nth-child(#$i)
animation-delay: # $i * -0.15 s;
background: #hsl(100 + $i * 15, 80%, 60%);
@keyframes move
0%
--angle: 0deg;
100%
--angle: 360deg;
借助了 SASS 完成了部分重复性代码,核心就是让小圆以不同的速率进行旋转动画,结果如下:
完整的代码,你可以戳这里:CSS Cos/Sin Math function - Loading animation
尝试使用三角函数实现波浪线
那么,三角函数还有什么作用吗?
我们来尝试点新奇的,借助三角函数实现曲线(波浪线)。
对 box-shadow
足够了解的同学应该知道,box-shadow
是支持多重阴影的,借助这个特性,出现了很多单标签,借助 box-shadow
来绘图的案例。
借助三角函数、以及box-shadow
是支持多重阴影的这两个特性,我们就可以利用它们来实现波浪线。
当然,可以还需要借助 SASS 简化手动书写的代码量。我们来看一个 DEMO:
<div></div>
<div></div>
<div></div>
@function shadowSet($vx, $vy, $color)
$shadow: 0 0 0 0 $color;
@for $i from 0 through 50
$x: calc(2 * sin(#$i * 15 * 1deg) * #$vy);
$y: $i * $vy;
$shadow: $shadow, #$x #$y 0 0 $color;
@return $shadow;
div
margin: auto;
width: 10px;
height: 10px;
border-radius: 50%;
background: #f00;
box-shadow: shadowSet(3px, 3px, #f00);
div:nth-child(2)
width: 6px;
height: 6px;
background: #fc0;
box-shadow: shadowSet(3px, 3px, #fc0);
div:nth-child(3)
width: 4px;
height: 4px;
background: #000;
box-shadow: shadowSet(2px, 2px, #000);
这样,我们就能得到 3 条波浪线:
单独看其中一个,其实是这样一坨 box-shadow
代码:
好吧,这个方法确实一定程度上弥补了之前 CSS 无法有效绘制波浪线的缺陷,但是,缺点也非常明显,编译后的代码量太多了!
完整的代码,你可以戳这里:CSS Cos/Sin Math And box-shadow
曲线创意构想
有了绘制曲线的能力,我们就能利用它在 CSS 中创造许多有美感、艺术性的效果。
我们可以尝试使用这些曲线,来制作书签图案:
代码也不复杂,我就不贴完整的代码了,感兴趣的可以戳这里:CodePen Demo - CSS Cos/Sin Math And box-shadow - bookmark
熟悉我的读者一定对 CSS-doodle 不陌生,袁川老师,也就是 CSS-doodle 库的作者,在他的 Codepen 首页背景板中,使用的就是使用了三角函数实现的一副纯 CSS 画作:
我之前也尝试使用三角函数,实现了一副丑一点的:
Codepen Demo -- CSS-Doodle fish 原生 CSS “杀死” 预处理器 Sass!
【CSDN 编者按】有着世界上最成熟、稳定和强大的专业级 CSS 扩展语言之称的 Sass,是 CSS 预处理器中的一种,其可编程能力较强,支持函数、列表、对象、判断、循环等等,凭借这些优势,其一度成为最受开发者喜爱的语言之一。但随着 CSS 的逐渐强大,以及 Less、Stylus 等其他 CSS 预处理器的诞生,Sass 光辉不再。
作者 | Cathy Dutton
译者 | 姜松浩,责编 | 屠敏
出品 | CSDN(ID:CSDNnews)
我也无意中(至少在开始时)从我的代码库中删除了所有Sass的痕迹。这不是我打算做的事情,但是我看到我的旧Sass文件的次数越多,我就会更加地质疑它是否为我的网站增加了价值,或者只是增加了额外的复杂性和依赖性。CSS近年来不断发展,最初导致我使用Sass的问题在今天似乎不再那么重要。
这种连锁反应是删除了媒体查询。当我转向CSS的一些更现代的特性时,用独特的代码来确定特定屏幕大小的需求被消除了。
Sass解决了什么问题?
当我第一次开始学习Sass(大约5年前或6年前)时,我对此持怀疑态度,但随着我建立越来越多的响应式网站,我开始意识到我可以通过从Sass函数和mixins中获得可重用的逻辑来节省多少时间。很明显,随着设备、视区和主题使用变量的改变,实现更新变得更容易处理。
我使用Sass的东西包括:
布局
变量
排版
布局
布局一直是困扰CSS的一个原因。在我最初决定使用Sass创建一个CSS网格时的一个关键因素,是流动或响应布局的转变相结合。
在Sass之前
得我在CSS中构建响应网格布局的第一次尝试,它涉及到为每一列创建一组实用程序类,然后用非语义类名(如col-span-1和col-span-4)污染标记。
.col-span-3 {
float: left;
width: 24%;
margin-left: 1%;
}
.col-span-4 {
float: left;
width: 32.3%;
margin-left: 1%;
}
.col-span-5 {
float: left;
width: 40.6%;
margin-left: 1%;
}
通过使用与变量配对的Sass mixin,我能够删除上面的实用程序类,并通过更改$gridColumns变量来创建更灵活的布局。
我的第一个网格mixin:
@mixin grid($colSpan, $gridColumns: 12, $margin: 1%,) {
$unitWidth: $gridColumns / $colSpan;
float:left;
width: (100 - $unitWidth * $margin) / $unitWidth;
margin: 0 $margin/2;
}
包括这样实现:
.sidebar {
@include grid(3);
}
.main-content {
@include grid(9);
}
@media only screen and (max-width: 480px) {
.sidebar {
@include grid(12);
}
.main-content {
@include grid(12);
}
}
CSS网格
CSS 网格的引入消除了任何对此方面的需求,你不再需要在Sass或任何其他处理器中构建具有实用程序类的网格系统。Rachel Andrew说这样最好......
你不需要一个工具来帮助你让它看起来像你有一个网格,而你实际上有一个网格!——Rachel Andrew,你不需要基于CSS网格的网格系统。
下面的代码创建了一个响应式布局,可根据内容的最小和最大宽度进行调整,而不是根据预先设置的设备大小进行调整。
.project {
display: grid;
grid-template-columns: repeat( auto-fill, minmax(12em, 1fr) );
grid-gap: 1em;
}
从基于Sass的网格迁移到CSS网格是一种相对无痛的体验,它不仅减少了我对Sass的依赖,还使我能够创建更灵活的代码库,开辟了更广泛的设计可能性并允许我围绕内容构建网站而不是媒体查询。
切换到我的布局的原生CSS的明显缺点是浏览器的支持有限,或者仅仅是我认为这样。目前大多数现代浏览器都支持网格,前缀为IE11和IE10。自动填充和自动调整支持较少,但是可以使用功能查询轻松解决此问题。
变量
变量是一个可能会改变的值,就CSS来说,变量是我不知道的,直到我拥有它时我才能知道。如今我的大多数项目都遵循ITCSS方法,因此开始使用包含项目变量的设置文件。通常我会为字体,颜色和媒体查询设置变量。
我老的Sass是这样的:
/* COLORS */
$colors: (
"black": #2a2a2a,
"white": #fff,
"grey-light": #ccc7c3,
"grey-dark": #2a2a2a,
"accent": #ffa600,
"off-white": #f3f3f3,
"sky-blue": #ccf2ff
);
/* BREAKPOINTS */
$breakpoints: (
"break-mobile": 290px,
"break-phablet": 480px,
"break-tablet": 768px,
"break-desktop": 1020px,
"break-wide": 1280px
);
/* TYPOGRAPHY */
$font-stack: (
decorative: #{'oswald', Helvetica, sans-serif},
general: #{'Helvetica Neue', Helvetica, Arial, sans-serif}
);
使用这样的变量或映射,我可以快速轻松地进行站点范围的更改。它还有助于防止在大型代码库中常见的多个阴影、颜色变化和异常现象的累积,特别是对于悬停状态、阴影、边框等。
例如:
.button {
background-color: #4CAF50; /* Green */
}
.button:hover {
background-color: #3F8C42; /* Dark Green */
}
.button:active {
background-color: #266528; /* Darker Green */
}
可以使用sass变量和颜色函数重写如下:
$button-colour: #4CAF50;
.button {
background-color: $button-colour;
}
.button:hover {
background-color: darken($button-colour, 20%);
}
.button:active {
background-color: darken($button-colour, 50%);
}
那么都有什么改变?
CSS自定义属性不仅可以替换预处理器变量,还可以动态更新(而不是在构建时编译)。这允许在运行时使用Javascript更改值,并且可以在不需要mixins和函数来智能级联的情况下进行范围调整。
:root {
--button-color: #4CAF50;
}
.button {
background-color: var(--button-color);
}
header
.button {
--button-color: #000000;
background-color: var(--button-color);
}
像Sass中可用的颜色操作也可以使用color-mod函数在原生CSS中使用。
:root {
--button-color: #4CAF50;
}
.button:hover {
color: color-mod(var(--button-color) tint(50%));
}
不幸的是,这仍处于公开工作的草案阶段,因此暂时我决定删除这样的效果并用全彩色更改和文本效果替换它们。
.button {
background: var(--colour-dark);
}
.button:hover {
background: var(--colour-bright);
text-decoration: underline;
}
但是,如果你真的想要使用它们,那么有一些关于包含postcss-color-mod-function(https://github.com/jonathantneal/postcss-color-mod-function)的PostCSS解决方法。
排版
最后排版,在以前的代码库中我使用Sass创建响应式排版和间距。像下面的Mixins,使我可以轻松地自动更改不同的屏幕尺寸和设备。
@mixin typography($size) {
font-size: $size;
@include mq(break-desktop) {
font-size: $size * 1.2;
}
}
现在我可以使用calc和viewport单元来代替原生CSS执行theese计算。
:root {
--font-size: calc(18px + 0.25vw)
}
body {
font-size: var(--font-size);
}
未来
CSS正朝着一个更为内容优先的规范迈进,而CSS网格也有flexbox和大小调整属性,如min-content、max-content和fit-content以及未来发展的CSS Grid Layout Module Level 2中的Subgrid等。
所有这些功能使原生CSS更具吸引力。
原文:https://cathydutton.co.uk/posts/why-i-stopped-using-sass/
本文为 CSDN 翻译,转载请注明来源出处。
【END】
作为码一代,想教码二代却无从下手:
听说少儿编程很火,可它有哪些好处呢?
孩子多大开始学习比较好呢?又该如何学习呢?
最新的编程教育政策又有哪些呢?
下面给大家介绍CSDN新成员:极客宝宝(ID:geek_baby)
戳他了解更多↓↓↓
热 文 推 荐
点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。
以上是关于现代 CSS 解决方案:CSS 原生支持的三角函数的主要内容,如果未能解决你的问题,请参考以下文章