马黑黑 发表于 2025-7-15 13:57

在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 标签完美定位了,它们将长成楼下的样纸——


马黑黑 发表于 2025-7-15 13:58

<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>

马黑黑 发表于 2025-7-15 14:05

在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 */

马黑黑 发表于 2025-7-15 14:13

显然用 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>

红影 发表于 2025-7-15 16:33

粒子最大化的半径绕椭圆圆周布局,用css也能弄出来,只是有多少个粒子,就要写多少个。还是JS方便{:4_187:}

红影 发表于 2025-7-15 16:35

“每一个标签平均 30 个弧度”,用360除以12得到的是度数吧,不是弧度呢{:4_203:}

杨帆 发表于 2025-7-15 17:44

讲的真好,谢谢马老师经典讲授{:4_190:}

马黑黑 发表于 2025-7-15 18:02

红影 发表于 2025-7-15 16:33
粒子最大化的半径绕椭圆圆周布局,用css也能弄出来,只是有多少个粒子,就要写多少个。还是JS方便

少量几个时可以考虑只用CSS

马黑黑 发表于 2025-7-15 18:02

杨帆 发表于 2025-7-15 17:44
讲的真好,谢谢马老师经典讲授

{:4_191:}

马黑黑 发表于 2025-7-15 18:02

红影 发表于 2025-7-15 16:35
“每一个标签平均 30 个弧度”,用360除以12得到的是度数吧,不是弧度呢

CSS自动处理了角度和弧度的关系,这里为了简化,不讲那么多

红影 发表于 2025-7-15 20:15

马黑黑 发表于 2025-7-15 18:02
少量几个时可以考虑只用CSS

是的,5个以内的一个个写我觉得还行{:4_173:}

红影 发表于 2025-7-15 20:16

马黑黑 发表于 2025-7-15 18:02
CSS自动处理了角度和弧度的关系,这里为了简化,不讲那么多

原来CSS可以自动处理,这个还不知道呢{:4_204:}

马黑黑 发表于 2025-7-15 21:01

红影 发表于 2025-7-15 20:16
原来CSS可以自动处理,这个还不知道呢

它就直接处理角度,后台当然会使用三角函数相关原理去计算

红影 发表于 2025-7-15 22:12

马黑黑 发表于 2025-7-15 21:01
它就直接处理角度,后台当然会使用三角函数相关原理去计算

要是都这样就好了,需要自己去转化弧度角度是麻烦事呢。

马黑黑 发表于 2025-7-15 22:39

红影 发表于 2025-7-15 22:12
要是都这样就好了,需要自己去转化弧度角度是麻烦事呢。

角度转弧度,那个公式应该会吧?

红影 发表于 2025-7-16 10:31

马黑黑 发表于 2025-7-15 22:39
角度转弧度,那个公式应该会吧?

会的,那个简单。

马黑黑 发表于 2025-7-16 13:20

红影 发表于 2025-7-16 10:31
会的,那个简单。

俺文盲就弄不清楚了

红影 发表于 2025-7-17 21:19

马黑黑 发表于 2025-7-16 13:20
俺文盲就弄不清楚了

你都在考我了,你自己当然更清楚了啊{:4_173:}

马黑黑 发表于 2025-7-17 21:46

红影 发表于 2025-7-17 21:19
你都在考我了,你自己当然更清楚了啊

俺这叫求教

红影 发表于 2025-7-17 22:04

马黑黑 发表于 2025-7-17 21:46
俺这叫求教

才不是呢,你这就是考试呢,我是被考的{:4_173:}
页: [1]
查看完整版本: 在CSS中使用正余弦函数