榨干脑细胞!纯js 3D旋转球特效,重温数学三角函数

1,643 阅读1分钟

在掘金上偶然看到jy发的旋转球特效,心血来潮研究下用纯js实现3D旋转球的特效。榨干了数亿脑细胞,花费整整一天的摸鱼时间才研究出用数学三角函数来实现效果。话不多说,让我细细讲解一番。

实现效果图如下:

第一步,实现一个平面圆

如图将圆平均分为n份,每个点之间的夹角为360 / n,圆的中心为(x, y, 0),圆的半径为r,圆上点的坐标如下图:

根据三角函数,可得圆点上坐标为Xn = x + sinα * r, Yn = y - cosα * r, Zn = 0

const centerX = r;
const centerY = r;
for (let j = 1; j <= num; j++) {
    const dom = document.querySelector(
      `.sphere .text:nth-child(${j})`
    );
    const a = Math.PI / 180;
    const angle = (360 / num) * (j - 1) * a;
    const w = dom.innerText.length * 16;
    dom.style.transform = `translateX(${centerX + r * Math.sin(angle)  - w / 2}px)     translateY(${centerY - r * Math.cos(angle)}px)`;
}

w是文字的总长度,减去 w / 2是为了将文字居中到点。

第二步,实现旋转圆面

计算沿y轴旋转θ角度的圆,(Xn, Yn, Zn) ---旋转θ---> (Xr, Yr, Zr)

分析:

  • 旋转前的点和旋转后的点在一个圆上,圆的半径r1等于sinα * r
  • y轴不变,Xr = x + r1 * cosθ,Yr = Yn, Zr = r1 * sinθ
const r1 = r * Math.sin(angle);
dom.style.transform = `translateX(${
  centerX + r1 * Math.cos(a1) - w / 2
}px) translateY(${centerY - r * Math.cos(angle)}px) translateZ(${
  r1 * Math.sin(a1)
}px)`;

w是文字的总长度,减去 w / 2是为了将文字居中到点。

第三步,旋转球体

球体旋转β角度,文字也会跟着旋转,为了使文字始终在平面上,文字需要反向旋转β

this.angle = 0;
function rotate() {
    this.timer = setInterval(() => {
      this.sphere.style.transform = `rotateY(${this.angle}deg)`;
      document.querySelectorAll('.sphere .text').forEach((ele) => {
        let transform = ele.style.transform;
        if (!transform.includes('rotateY')) {
          ele.style.transform = `${transform} rotateY(-${this.angle}deg)`;
        } else {
          ele.style.transform = transform.replace(
            /rotateY\([-0-9]+deg\)/,
            `rotateY(-${this.angle}deg)`
          );
        }
      });
      this.angle += β;
      if (this.angle === 360) {
        this.angle = 0;
      }
    }, 100);
}

源代码详见👇