Three.js问题:如何更改对象旋转中心实现月球绕地球公转?
解决Three.js月球绕地球公转的问题
嘿,别着急!这是Three.js新手最容易踩的坐标层级坑,我刚学的时候也遇到过一模一样的问题😉
问题根源
你现在的月球位置是直接基于世界原点(也就是太阳的位置0,0,0)计算的,所以它自然会绕太阳转。要实现月球绕地球转,得利用Three.js的**对象层级(Group)**来管理父子关系——把地球和月球放进同一个组里,让整个组绕太阳公转,月球再相对于组(也就是地球的位置)做圆周运动。
具体解决方案
第一步:初始化阶段创建地球组
先在你的场景初始化代码里,新增一个Group对象,把地球、云层和月球都加到这个组里:
// 创建地球组,用来承载地球、云层和月球 const earthGroup = new THREE.Group(); earthGroup.name = "earthGroup"; scene.add(earthGroup); // 将已有的地球、云层、月球添加到组中 earthGroup.add(scene.getObjectByName("earth")); earthGroup.add(scene.getObjectByName("clouds")); earthGroup.add(scene.getObjectByName("moon"));
第二步:修改render函数
调整渲染逻辑,让组绕太阳公转,月球相对于组做独立的圆周运动(记得给月球单独加角度变量,避免和地球公转同步):
// 新增月球的公转角度变量,放在render函数外部(全局/模块级) let moonAngle = 0; function render(){ cameraControls.update(); angle += 0.01; moonAngle += 0.05; // 月球转得比地球快,更贴近真实效果 // 太阳自转 scene.getObjectByName("sun").rotation.y += 0.005; // 地球组整体绕太阳公转(把原来地球的公转逻辑移到组上) const earthGroup = scene.getObjectByName("earthGroup"); earthGroup.position.x = 80 * Math.cos(angle); earthGroup.position.z = 80 * Math.sin(angle); // 地球自转 scene.getObjectByName("earth").rotation.y += 0.015; // 云层自转 scene.getObjectByName("clouds").rotation.y += 0.017; // 月球相对于地球组公转(现在的position是相对于地球的位置) const moon = scene.getObjectByName("moon"); moon.position.x = 15 * Math.cos(moonAngle); // 月球轨道半径设小一点,比如15 moon.position.z = 15 * Math.sin(moonAngle); moon.rotation.y += 0.020; // 月球自转 renderer.render(scene, camera); requestAnimationFrame(render); }
原理说明
在Three.js里,每个对象的position、rotation都是相对于父对象的。把月球设为地球组的子对象后,月球的坐标原点就变成了地球组的中心(也就是地球的位置)。地球组绕太阳转,月球同时绕地球组的中心转,这样就实现了月球绕地球公转、同时跟着地球绕太阳转的效果啦!
小优化建议
- 可以调整
moonAngle的增量(比如改成0.027),让月球的公转周期更贴近真实(月球公转周期约27天,地球公转约365天,角速度比约13.5:1) - 如果想让月球始终同一面朝向地球,可以把月球的自转角度和公转角度绑定,比如
moon.rotation.y = moonAngle;
内容的提问来源于stack exchange,提问作者Jessica MC
相关产品推荐
相关产品推荐

