最省事路径是用three.js搭配three.textgeometry或troika-three-text;需用fibonacci球面采样均匀布词、手动设置quaternion使文字正对摄像机、加载json字体、词超50个时关闭阴影。

用 Three.js 实现球形词云最省事的路径
直接用 three.js + THREE.TextGeometry 或 troika-three-text 是目前唯一能稳定控制每个词位置、大小、朝向且保持可读性的方案。纯 CSS 3D 或 Canvas 手搓球面投影,要么文字扭曲严重,要么交互卡顿,还容易在 Safari 上失焦。
关键不是“怎么转起来”,而是“怎么让每个词真正贴在球面上且正对摄像机”。默认的球面坐标映射只是把文字放在球表面,不调整旋转,结果全是歪的、倒的、侧躺的。
- 必须手动计算每个词的
position和quaternion(或用lookAt) - 字体不能用浏览器默认字体——
TextGeometry依赖FontLoader加载 JSON 字体(如helvetiker_bold.typeface.json),否则报错TypeError: font.generateShapes is not a function - 词多于 50 个时,建议关掉阴影、禁用
castShadow和receiveShadow,不然帧率掉到 10fps 以下
词的位置怎么均匀分布在球面上
别用随机 Math.random() 生成经纬度——会聚堆在两极。要用“Fibonacci sphere sampling”算法,它能逼近均匀分布,代码不到 10 行:
function fibonacciSphere(samples) {
const points = [];
const phi = Math.PI * (3 - Math.sqrt(5)); // 黄金角
for (let i = 0; i <p>返回的每个点已经是单位球面上的归一化坐标,直接赋给 <code>mesh.position.set(x, y, z)</code> 即可。注意:后续调用 <code>mesh.lookAt(0, 0, 0)</code> 会让文字背面朝外,得改成 <code>mesh.lookAt(new THREE.Vector3().negate())</code> 或直接设 <code>mesh.rotation.copy(new THREE.Euler().setFromQuaternion(q))</code>。</p><h3>为什么不用 D3.js + SVG 做球形词云</h3><p>因为 SVG 没有真正的 3D 渲染管线。所谓“球形”,只是用 <code>transform: rotateX() rotateY()</code> 模拟,本质还是平面投影。问题非常明显:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter"><img
src="https://img.php.cn/upload/skill/000/000/081/179232667384043.jpg" alt="html-to-pptx-converter" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter" class="overflowclass">html-to-pptx-converter</a>
<p class="overflowclass">使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 文字重叠无法深度排序(
z-index在 3D transform 下失效) - 缩放时字体边缘发虚(SVG 被当位图拉伸)
- 滚动或切换 Tab 后,
requestAnimationFrame容易中断,旋转突然卡住 - 手机端 touchmove 事件和
transform冲突,拖拽一顿一顿
如果你只需要静态图,用 Python 的 wordcloud 库导出球面 UV 展开图再 PS 合成更快。但要真旋转、可交互、支持点击词跳转?绕不开 WebGL。
移动端适配和性能踩坑点
在 iOS Safari 上,three.js 默认启用抗锯齿(antialias: true)会导致内存暴涨,尤其词超过 30 个时,页面直接崩溃。必须显式关掉:
const renderer = new THREE.WebGLRenderer({ antialias: false });
另外两个硬性限制:
- 字体大小别设
0.1这种小数——iOS 对 subpixel rendering 支持差,文字糊成一片;建议最小用0.2,并统一乘以devicePixelRatio - 不要监听
window.resize后立刻调用renderer.setSize(),需加防抖,否则快速横竖屏切换时触发多次 resize,Three.js 内部 buffer 重建失败,报错WebGL: INVALID_OPERATION: bindBuffer: object not from this context
球面词云真正的难点不在“转”,而在每个词的法线对齐、远近缩放一致性、以及低功耗设备上的帧率兜底——这些细节没压住,看起来就是廉价动画。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










