如何让ThreeJS构建的新泽西3D地图绕自身固定轴旋转?
问题描述
我使用d3js结合topo.json构建了新泽西的3D地图,希望实现地图绕自身固定轴自主旋转,但目前地图却像绕球体一样在场景中滚动,而非绕自身旋转。我参考相关示例尝试设置pivot对象:
var pivot = new THREE.Object3D(); pivot.position.set(0,0,0); pivot.rotation.set(0,0,0); scene.add(pivot);
但问题仍未解决。期望实现的绕自身旋转效果类似以下示例:
示例代码
JavaScript
var camera, scene, renderer, mesh; var local = false; init(); animate(); function init() { // 相机设置 camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 ); camera.position.set( 1, 2, - 2 ); // 场景设置 scene = new THREE.Scene(); camera.lookAt( scene.position ); // 立方体设置 var geometry = new THREE.BoxBufferGeometry( 0.5, 0.5, 0.5 ); var material = new THREE.MeshNormalMaterial(); mesh = new THREE.Mesh( geometry, material ); mesh.position.set(0.5,0.5,0.5); // 注意:在旋转网格前,全局和局部旋转是相同的 mesh.rotation.y = 0.5; scene.add( mesh ); // 添加网格和坐标轴 scene.add( new THREE.GridHelper( 4, 10 ) ); scene.add( new THREE.AxesHelper() ); // 添加渲染器 renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); // 创建旋转切换按钮 var button = document.createElement("button"); button.innerText = "局部旋转关闭"; button.onclick = () => { local = !local if (local) button.innerText = "局部旋转开启"; else button.innerText = "局部旋转关闭"; }; document.body.appendChild(button); } function animate() { requestAnimationFrame( animate ); // 全局旋转 if (!local) mesh.rotation.x += 0.03; // 局部旋转 else mesh.rotateX(0.03); renderer.render( scene, camera ); }
CSS
body { margin: 0; } button { position: absolute; top: 10px; left: 10px; }
HTML
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
解决方案
核心问题在于你未将地图模型挂载到pivot对象上,且pivot的位置未对准地图的几何中心。以下是两种可行的解决方法:
方法一:使用Pivot容器(推荐)
计算地图模型的几何中心
地图加载完成后,通过包围盒获取模型的中心坐标:// 假设你的地图模型变量为mapMesh const boundingBox = new THREE.Box3().setFromObject(mapMesh); const center = boundingBox.getCenter(new THREE.Vector3());正确配置Pivot并挂载模型
将pivot定位到地图中心,调整模型位置使其以pivot为原点,最后将模型添加到pivot中:const pivot = new THREE.Object3D(); pivot.position.copy(center); // 将pivot放置在地图几何中心 mapMesh.position.sub(center); // 调整模型位置,使其相对pivot居中 pivot.add(mapMesh); scene.add(pivot);实现自主旋转
在动画循环中旋转pivot,地图会自然绕自身中心旋转:function animate() { requestAnimationFrame(animate); pivot.rotation.y += 0.01; // 绕Y轴持续旋转,可替换为X/Z轴 renderer.render(scene, camera); }
方法二:直接调整模型坐标系
如果不想使用pivot,可以将模型的几何中心移到自身局部坐标系原点,之后直接使用局部旋转方法:
// 计算模型中心并平移几何体 const boundingBox = new THREE.Box3().setFromObject(mapMesh); const center = boundingBox.getCenter(new THREE.Vector3()); mapMesh.geometry.translate(-center.x, -center.y, -center.z); // 动画循环中使用局部旋转 function animate() { requestAnimationFrame(animate); mapMesh.rotateY(0.01); // 绕自身Y轴旋转 renderer.render(scene, camera); }
内容的提问来源于stack exchange,提问作者Scared Sandwich
相关产品推荐
相关产品推荐

