You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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容器(推荐)

  1. 计算地图模型的几何中心
    地图加载完成后,通过包围盒获取模型的中心坐标:

    // 假设你的地图模型变量为mapMesh
    const boundingBox = new THREE.Box3().setFromObject(mapMesh);
    const center = boundingBox.getCenter(new THREE.Vector3());
    
  2. 正确配置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);
    
  3. 实现自主旋转
    在动画循环中旋转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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:36:26