各位前端的侠士们,晚上好!今天咱们来聊点刺激的,关于CSS Trigonometric Functions,也就是CSS三角函数 (sin()
, cos()
, tan()
, atan()
, asin()
, acos()
) 的提案。别害怕,虽然听起来像数学课,但其实有了它们,咱们就能在CSS里玩转复杂的形状和动画,摆脱图片和SVG的束缚,想想都觉得兴奋!
开场白:CSS,不止于盒模型
咱们都知道,CSS的世界里,盒模型是基石。但时间长了,天天对着矩形、圆形,是不是有点审美疲劳?想象一下,如果咱们能用CSS直接绘制出各种奇形怪状,那该有多酷!这就是CSS三角函数提案的意义所在:它试图打破盒模型的限制,赋予CSS更强大的图形绘制能力。
什么是CSS三角函数?
简单来说,CSS三角函数就是允许咱们在CSS里使用正弦 (sin()
)、余弦 (cos()
)、正切 (tan()
) 以及对应的反函数 (asin()
, acos()
, atan()
)。这些函数接收一个角度作为参数,返回一个介于 -1 和 1 之间的数值 (对于 sin()
和 cos()
),或者一个角度值 (对于反函数)。
为什么要用CSS三角函数?
- 动态性: 可以根据屏幕尺寸、用户交互等动态调整形状和动画,实现真正的响应式设计。
- 性能: 相比于使用图片或SVG,CSS绘制的图形通常具有更好的性能,尤其是对于复杂的动画效果。
- 灵活性: 可以创造出各种独特的形状和动画,突破传统CSS的限制。
- 可维护性: 代码可读性更高,更易于维护和修改。
- 减少HTTP请求: 避免使用图片,减少HTTP请求,加快页面加载速度。
CSS三角函数的基本用法
先来看几个简单的例子,了解一下这些函数的基本用法。
/* 使用 sin() 和 cos() 创建一个圆形路径上的点 */
:root {
--angle: 45deg; /* 定义一个角度变量 */
--x: calc(50px + 50px * cos(var(--angle))); /* x坐标 */
--y: calc(50px + 50px * sin(var(--angle))); /* y坐标 */
}
.circle-point {
position: absolute;
left: var(--x);
top: var(--y);
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
在这个例子中,我们使用了 sin()
和 cos()
函数来计算一个点在圆形路径上的坐标。--angle
变量定义了角度,--x
和 --y
变量分别计算了点的 x 和 y 坐标。通过改变 --angle
的值,我们可以让这个点沿着圆形路径移动。
sin()
, cos()
, tan()
函数
这三个是最常用的三角函数,它们的用法也很简单:
sin(angle)
:返回给定角度的正弦值。cos(angle)
:返回给定角度的余弦值。tan(angle)
:返回给定角度的正切值。
角度可以使用 deg
(度)、rad
(弧度)、grad
(百分度) 或 turn
(圈数) 作为单位。
.element {
transform: rotate(calc(30deg * sin(45deg))); /* 旋转角度 */
width: calc(100px * cos(60deg)); /* 宽度 */
height: calc(50px * tan(30deg)); /* 高度 */
}
反三角函数:asin()
, acos()
, atan()
反三角函数用于计算给定值的角度。
asin(number)
:返回给定数字的反正弦值 (弧度)。数字必须在 -1 到 1 之间。acos(number)
:返回给定数字的反余弦值 (弧度)。数字必须在 -1 到 1 之间。atan(number)
:返回给定数字的反正切值 (弧度)。
.element {
--angle: calc(asin(0.5)); /* 计算反正弦值,结果是弧度 */
transform: rotate(calc(var(--angle) * 180 / pi())); /* 将弧度转换为度数 */
}
注意,反三角函数返回的是弧度值,如果需要转换为度数,可以使用 calc()
函数进行转换,其中 pi()
函数返回圆周率 π。
atan2()
函数
atan2(y, x)
函数返回点 (x, y) 与原点之间的角度,考虑到 x 和 y 的符号,可以确定角度所在的象限。这在创建指向特定位置的动画时非常有用。
:root {
--mouse-x: 0; /* 鼠标x坐标 */
--mouse-y: 0; /* 鼠标y坐标 */
--angle: calc(atan2(var(--mouse-y), var(--mouse-x))); /* 计算角度 */
}
.arrow {
transform: rotate(calc(var(--angle) * 180 / pi())); /* 旋转箭头 */
}
/* JavaScript 更新鼠标坐标 */
document.addEventListener('mousemove', (event) => {
document.documentElement.style.setProperty('--mouse-x', event.clientX);
document.documentElement.style.setProperty('--mouse-y', event.clientY);
});
在这个例子中,箭头会根据鼠标的位置旋转,始终指向鼠标。
实际应用:创建复杂形状和动画
有了这些三角函数,咱们就可以在CSS里创建各种复杂的形状和动画了。
1. 星形
<div class="star"></div>
.star {
position: relative;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 35px solid red; /* 初始三角形 */
transform-origin: 50% 100%; /* 旋转中心 */
}
.star::before,
.star::after {
content: '';
position: absolute;
top: 0;
left: -50px;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 35px solid red;
transform-origin: 50% 100%;
}
.star::before {
transform: rotate(calc(72deg * 1)); /* 旋转72度 */
}
.star::after {
transform: rotate(calc(72deg * 2)); /* 旋转144度 */
}
如果使用三角函数,我们可以更加灵活的控制星形的形状,例如控制内角,外角,半径等。
<div class="star-trigonometric"></div>
.star-trigonometric {
--points: 5; /* 星星角数 */
--radius: 50px; /* 星星半径 */
--inner-radius: 25px; /* 内半径 */
position: relative;
width: calc(var(--radius) * 2);
height: calc(var(--radius) * 2);
background: black;
clip-path: polygon(
/* 使用三角函数计算每个点的坐标 */
/* 循环生成每个点的坐标 */
/* 外部点 */
calc(var(--radius) + var(--radius) * cos(calc(-90deg + var(--i) * (360deg / var(--points))))) calc(var(--radius) + var(--radius) * sin(calc(-90deg + var(--i) * (360deg / var(--points))))),
/* 内部点 */
calc(var(--radius) + var(--inner-radius) * cos(calc(-90deg + (var(--i) + 0.5) * (360deg / var(--points))))) calc(var(--radius) + var(--inner-radius) * sin(calc(-90deg + (var(--i) + 0.5) * (360deg / var(--points)))))
);
--i: 0; /* 用于循环的变量,不能直接在CSS中使用,所以需要配合javascript */
}
/*使用javascript 动态生成 clip-path */
const star = document.querySelector('.star-trigonometric');
let polygonString = '';
const points = 5;
const radius = 50;
const innerRadius = 25;
for (let i = 0; i < points; i++) {
const angle = -Math.PI / 2 + i * (2 * Math.PI / points);
const innerAngle = -Math.PI / 2 + (i + 0.5) * (2 * Math.PI / points);
const x1 = radius + radius * Math.cos(angle);
const y1 = radius + radius * Math.sin(angle);
const x2 = radius + innerRadius * Math.cos(innerAngle);
const y2 = radius + innerRadius * Math.sin(innerAngle);
polygonString += `${x1}px ${y1}px, ${x2}px ${y2}px, `;
}
// 移除最后一个逗号和空格
polygonString = polygonString.slice(0, -2);
star.style.clipPath = `polygon(${polygonString})`;
说明:
--points
: 星星的角数。--radius
: 星星的外半径。--inner-radius
: 星星的内半径。- clip-path: 使用polygon()函数绘制星星的形状。
上述代码需要配合javascript来实现,因为CSS中没有循环语句,无法动态生成多个坐标点。
2. 波浪动画
<div class="wave"></div>
.wave {
position: relative;
width: 200px;
height: 100px;
overflow: hidden;
}
.wave::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 200%;
height: 50%;
background-color: blue;
animation: wave 5s linear infinite;
}
@keyframes wave {
0% {
transform: translateX(0) translateY(calc(10px * sin(0deg)));
}
100% {
transform: translateX(-50%) translateY(calc(10px * sin(360deg)));
}
}
在这个例子中,我们使用了 sin()
函数来控制波浪的垂直位置,创建了一个简单的波浪动画。
3. 螺旋线
<div class="spiral"></div>
.spiral {
position: relative;
width: 200px;
height: 200px;
}
.spiral::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 2px;
height: 2px;
background-color: red;
animation: spiral 5s linear infinite;
}
@keyframes spiral {
0% {
transform: translate(-50%, -50%) rotate(0deg) translateX(0px);
}
100% {
transform: translate(-50%, -50%) rotate(3600deg) translateX(100px);
}
}
这个例子中,我们结合了 rotate()
和 translateX()
变换,创建了一个螺旋线动画。
4. 使用 clip-path 创建复杂形状
clip-path
属性可以裁剪元素,使其显示为指定的形状。结合三角函数,我们可以创建各种复杂的裁剪路径。
<div class="clipped-shape"></div>
.clipped-shape {
width: 200px;
height: 200px;
background-color: green;
clip-path: polygon(
calc(50% + 50px * cos(0deg)) calc(50% + 50px * sin(0deg)),
calc(50% + 50px * cos(72deg)) calc(50% + 50px * sin(72deg)),
calc(50% + 50px * cos(144deg)) calc(50% + 50px * sin(144deg)),
calc(50% + 50px * cos(216deg)) calc(50% + 50px * sin(216deg)),
calc(50% + 50px * cos(288deg)) calc(50% + 50px * sin(288deg))
);
}
这个例子使用 clip-path
创建了一个五边形。
表格总结
函数 | 描述 | 参数 | 返回值 |
---|---|---|---|
sin(angle) |
返回给定角度的正弦值。 | 角度 (deg, rad, grad, turn) | 介于 -1 和 1 之间的数值 |
cos(angle) |
返回给定角度的余弦值。 | 角度 (deg, rad, grad, turn) | 介于 -1 和 1 之间的数值 |
tan(angle) |
返回给定角度的正切值。 | 角度 (deg, rad, grad, turn) | 数值 |
asin(number) |
返回给定数字的反正弦值 (弧度)。数字必须在 -1 到 1 之间。 | 数字 (-1 到 1) | 弧度 |
acos(number) |
返回给定数字的反余弦值 (弧度)。数字必须在 -1 到 1 之间。 | 数字 (-1 到 1) | 弧度 |
atan(number) |
返回给定数字的反正切值 (弧度)。 | 数字 | 弧度 |
atan2(y, x) |
返回点 (x, y) 与原点之间的角度 (弧度),考虑到 x 和 y 的符号。 | y, x | 弧度 |
pi() |
返回圆周率 π 的值。 | 无 | 圆周率 π 的值 (约等于 3.141592653589793) |
注意事项
- 兼容性: 截至目前(2024年),CSS三角函数提案仍在草案阶段,尚未被所有浏览器完全支持。使用前请务必检查浏览器的兼容性。
- 性能: 复杂的三角函数计算可能会影响性能,尤其是在动画中。请谨慎使用,并进行性能测试。
- 可读性: 复杂的三角函数表达式可能会降低代码的可读性。建议使用变量和注释来提高代码的可读性。
总结
CSS三角函数提案为咱们打开了一扇新的大门,让咱们可以在CSS里创造出各种复杂的形状和动画。虽然目前兼容性还不是很好,但相信随着提案的推进和浏览器的支持,它将成为前端开发中一个非常有用的工具。希望今天的讲解能帮助大家更好地理解和使用CSS三角函数,创造出更加炫酷的网页效果!
下次再见!