在CSS中使用正余弦函数
本帖最后由 马黑黑 于 2025-7-15 14:57 编辑先看代码:
<style>
.lzpa {
position: relative;
margin: 100px auto;
width: 600px;
height: 400px;
border: 1px solid gray;
}
li-zi {
position: absolute;
left: calc( 275px + 275px * cos(var(--deg)) );
top: calc( 175px + 175px * sin(var(--deg)) );
width: 50px;
height: 50px;
border-radius: 50%;
background: radial-gradient(at 60% 60%, lightgreen 1%, green);
}
li-zi:nth-of-type(1) { --deg: 0deg; }
li-zi:nth-of-type(2) { --deg: 90deg; }
li-zi:nth-of-type(3) { --deg: 180deg; }
li-zi:nth-of-type(4) { --deg: 270deg; }
</style>
<div class="lzpa">
<li-zi></li-zi>
<li-zi></li-zi>
<li-zi></li-zi>
<li-zi></li-zi>
</div>
代码结构很简单:CSS和HTML均围绕 li-zi 这个自定义元素展开,具体是先建立一个用来装载 li-zi 标签的容器元素,CSS中设置其为相对定位、居中、宽高为600*400、有个边框以便观察 li-zi 的位置;其次创建4个自定义标签 li-zi ,其CSS样式设为绝对定位、left和top属性定位、50*50的宽高、圆形、带美丽的径向渐变背景。
重点在 li-zi 选择器的 left 和 top 属性值的设置:
我们用 calc 函数来计算属性值,calc ( 运算式子 ),式子里数字需要带单位,例如 px、deg 像素和角度单位等。现在来理解calc函数的运算式子。
首先,我们的意图是让 li-zi 标签在容器元素内以最大化的半径绕椭圆圆周布局,所以,我们先得会如何求椭圆圆周上任一点的坐标(x, y)值,rx 和 ry 分别为x、y两个方向上的椭圆半径:
x = rx + rx *sin(弧度)
y =ry + ry *cos(弧度)
放到 li-zi 选择器的 left 和 top 属性,rx = 容器元素宽度 - li-zi宽度的一半,ry = 容器元素高度 - li-zi高度的一半,所以,式子是酱紫(注意数字要带单位):
left: 275px + 275rx *cos(弧度);
top:175px + 175px *sin(弧度);
要用 calc 函数将式子纳入其中,且弧度使用CSS变量 --deg 来表示,这个变量将在每一个li-zi 设定中单独赋值。最后,left 和 top 属性设置是酱紫:
left: calc( 275px + 275px * cos(var(--deg)) );
top: calc( 175px + 175px * sin(var(--deg)) );
这就将 li-zi 标签完美定位了,它们将长成楼下的样纸——
<style>
.lzpa {
position: relative;
margin: 100px auto;
width: 600px;
height: 400px;
border: 1px solid gray;
}
li-zi {
position: absolute;
left: calc( 275px + 275px * cos(var(--deg)) );
top: calc( 175px + 175px * sin(var(--deg)) );
width: 50px;
height: 50px;
border-radius: 50%;
background: radial-gradient(at 60% 60%, lightgreen 1%, green);
}
li-zi:nth-of-type(1) { --deg: 0deg; }
li-zi:nth-of-type(2) { --deg: 90deg; }
li-zi:nth-of-type(3) { --deg: 180deg; }
li-zi:nth-of-type(4) { --deg: 270deg; }
</style>
<div class="lzpa">
<li-zi></li-zi>
<li-zi></li-zi>
<li-zi></li-zi>
<li-zi></li-zi>
</div> 在CSS中,如何给每一个 li-zi 标签的 --deg 变量单独赋值:
360 / 总数
例如,需要创建 12 个 li-zi 标签,则每一个标签平均 30 个弧度,酱紫——
li-zi:nth-of-type(1) { --deg: 0deg; } /* 第一个是 0 */
li-zi:nth-of-type(2) { --deg: 30deg; } /* 第二个是 30 */
li-zi:nth-of-type(3) { --deg: 30deg; } /* 第三个是 60 */
/* 这里是其它的伪类 */
li-zi:nth-of-type(12) { --deg: 300deg; } /* 第十二个是 300 */ 显然用 JS 动态生成 li-zi 标签比较省事,以下是完整的示例代码:
<style>
.lzpa {
position: relative;
margin: 100px auto;
width: 600px;
height: 400px;
border: 1px solid gray;
}
li-zi {
position: absolute;
left: calc( 275px + 275px * cos(var(--deg)) );
top: calc( 175px + 175px * sin(var(--deg)) );
width: 50px;
height: 50px;
border-radius: 50%;
background: radial-gradient(at 60% 60%, lightgreen 1%, green);
}
</style>
<div class="lzpa"></div>
<script>
var lzpa = document.querySelector('.lzpa'); // 获取容器元素
var total = 12; // 总数
Array.from({ length: total }).forEach( (lz, idx) => {
lz = document.createElement('li-zi');
lz.style.cssText += `
--deg: ${idx * 360 / total}deg;
// ... 这里是其它CSS样式代码(如果需要)
`;
lzpa.appendChild(lz);
});
</script> 粒子最大化的半径绕椭圆圆周布局,用css也能弄出来,只是有多少个粒子,就要写多少个。还是JS方便{:4_187:} “每一个标签平均 30 个弧度”,用360除以12得到的是度数吧,不是弧度呢{:4_203:} 讲的真好,谢谢马老师经典讲授{:4_190:} 红影 发表于 2025-7-15 16:33
粒子最大化的半径绕椭圆圆周布局,用css也能弄出来,只是有多少个粒子,就要写多少个。还是JS方便
少量几个时可以考虑只用CSS 杨帆 发表于 2025-7-15 17:44
讲的真好,谢谢马老师经典讲授
{:4_191:} 红影 发表于 2025-7-15 16:35
“每一个标签平均 30 个弧度”,用360除以12得到的是度数吧,不是弧度呢
CSS自动处理了角度和弧度的关系,这里为了简化,不讲那么多 马黑黑 发表于 2025-7-15 18:02
少量几个时可以考虑只用CSS
是的,5个以内的一个个写我觉得还行{:4_173:} 马黑黑 发表于 2025-7-15 18:02
CSS自动处理了角度和弧度的关系,这里为了简化,不讲那么多
原来CSS可以自动处理,这个还不知道呢{:4_204:} 红影 发表于 2025-7-15 20:16
原来CSS可以自动处理,这个还不知道呢
它就直接处理角度,后台当然会使用三角函数相关原理去计算 马黑黑 发表于 2025-7-15 21:01
它就直接处理角度,后台当然会使用三角函数相关原理去计算
要是都这样就好了,需要自己去转化弧度角度是麻烦事呢。 红影 发表于 2025-7-15 22:12
要是都这样就好了,需要自己去转化弧度角度是麻烦事呢。
角度转弧度,那个公式应该会吧? 马黑黑 发表于 2025-7-15 22:39
角度转弧度,那个公式应该会吧?
会的,那个简单。 红影 发表于 2025-7-16 10:31
会的,那个简单。
俺文盲就弄不清楚了 马黑黑 发表于 2025-7-16 13:20
俺文盲就弄不清楚了
你都在考我了,你自己当然更清楚了啊{:4_173:} 红影 发表于 2025-7-17 21:19
你都在考我了,你自己当然更清楚了啊
俺这叫求教 马黑黑 发表于 2025-7-17 21:46
俺这叫求教
才不是呢,你这就是考试呢,我是被考的{:4_173:}
页:
[1]