3D 球体画廊组件(斐波那契球面分布,拖拽惯性旋转可调)

JSCSS 许可:自研原创

3D 球体画廊组件:JS 斐波那契球面算法均匀分布 12-80 个卡片,Pointer Events 拖拽旋转带惯性滑动,数量、半径、自动旋转速度可调,自研实现零依赖零图片。

效果演示(真实可交互)

🖱 拖拽旋转球体,松手后惯性滑动;数量/半径/自转速度可调

完整代码

球面分布采用经典斐波那契球面算法:第 i 个点的竖直分量 y = 1 - (2i+1)/n,水平角 θ = 黄金角 × i,如此生成的分布比经纬网均匀得多,不会在极点扎堆。每个卡片的变换为 rotateY(方位角) rotateX(纬度) translateZ(半径)——先转到所在经度,再抬到所在纬度,最后沿半径方向推出,即落在球面上且法线朝外。

<div class="scene" id="scene">
  <div class="sphere" id="sphere"></div>
</div>
.scene {
  height: 440px; perspective: 1100px;
  display: flex; align-items: center; justify-content: center;
  cursor: grab; user-select: none; touch-action: none;  /* 拖拽手感 */
}
.sphere {
  position: relative; width: 0; height: 0;
  transform-style: preserve-3d;
}
.item {
  position: absolute; width: 76px; height: 76px;
  margin-left: -38px; margin-top: -38px;
  border-radius: 16px; display: flex; align-items: center; justify-content: center;
}
// 斐波那契球面分布
function build(n, R) {
  sphere.innerHTML = '';
  const golden = Math.PI * (3 - Math.sqrt(5));
  for (let i = 0; i < n; i++) {
    const y = 1 - (2 * i + 1) / n;                 // 竖直分量
    const rad = Math.sqrt(Math.max(0, 1 - y * y)); // 纬度圈半径
    const th = golden * i;
    const az = Math.atan2(Math.cos(th) * rad, Math.sin(th) * rad) * 180 / Math.PI;
    const pol = Math.asin(y) * 180 / Math.PI;      // 纬度
    const el = document.createElement('div');
    el.className = 'item';
    el.style.transform = `rotateY(${az}deg) rotateX(${pol}deg) translateZ(${R}px)`;
    sphere.appendChild(el);
  }
}
// 拖拽旋转 + 惯性
scene.addEventListener('pointerdown', e => { dragging = true; lastX = e.clientX; lastY = e.clientY; });
scene.addEventListener('pointermove', e => {
  if (!dragging) return;
  ry += (e.clientX - lastX) * 0.35;
  rx -= (e.clientY - lastY) * 0.35;
  vx = (e.clientX - lastX) * 0.35;                // 记录速度 → 惯性
  vy = -(e.clientY - lastY) * 0.35;
  lastX = e.clientX; lastY = e.clientY;
  apply();
});
scene.addEventListener('pointerup', () => dragging = false);
// rAF 循环:无拖拽时按惯性衰减并叠加自动旋转

参数说明

参数位置说明
卡片数量n12-80 个,斐波那契分布自动均匀排布
球体半径R卡片距球心的距离,演示中 100-220px 可调
自动旋转循环中的 ry += speed·dt0-60°/s,拖拽时自动暂停
惯性衰减vx *= 0.94系数越接近 1,松手后滑得越久
拖拽灵敏度* 0.35光标位移到旋转角度的换算系数

兼容性与性能

常见问题

Q: 卡片在极点附近扎堆或球面分布不均? 若用经纬网格均匀取角就会出现极点堆积;请改用斐波那契球面算法(本组件默认),其黄金角步进保证任意数量下分布均匀。

Q: 拖拽方向感觉反了? 旋转符号取决于个人手感偏好,交换 ry += 与 rx -= 的符号即可反转;vx/vy 需与拖拽方向同步调整,否则松手后惯性方向相反。

Q: 移动端拖拽时页面跟着滚动? 在场景元素上设置 touch-action: none(演示已含),并确认事件用的是 Pointer Events 而不是纯 mouse 事件。

Q: 可以商用吗? 可以。本组件为粤喵自研原创代码,免费商用无需署名,卡片内容、数量、配色均可自由定制。

许可与来源

  • 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
  • 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
  • 首次发布:2026-09-01 · 最近更新:2026-09-01
  • 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
  • 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理

常见问题

这个组件可以商用吗?

可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。

浏览器兼容性如何?

支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。

怎么修改动画参数?

直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。

✍️ 作者与审核