在 CSS 中,存在許多數學函數,這些函數能夠通過簡單的計算操作來生成某些屬性值,例如 : * calc():用於計算任意長度、百分比或數值型數據,並將其作為 CSS 屬性值。 * min() 和 max():用於比較一組數值中的最大值或最小值,也可以與任意長度、百分比或數值型數據一同使用。 * c ...
在 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 畫作:
我之前也嘗試使用三角函數,實現了一副醜一點的: