Hello World - 旋转地球仪

知识库
知识库文档
/tech-stacks/threejs/examples/Hello World - 旋转地球仪.md

文档

Three.js 旋转地球仪

目标

用 Three.js 创建 3D 旋转地球仪:纹理贴图 + 星空粒子 + 鼠标交互旋转缩放。

完整代码

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>3D 地球仪</title>
  <style>
    body { margin: 0; overflow: hidden; background: #000; }
    canvas { display: block; }
    .info { position: fixed; bottom: 20px; left: 20px; color: white; font-family: system-ui; opacity: 0.7; }
  </style>
</head>
<body>
  <div class="info">🌍 拖拽旋转 · 滚轮缩放</div>

  <script type="importmap">
  {
    "imports": {
      "three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js",
      "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/"
    }
  }
  </script>

  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

    // 场景
    const scene = new THREE.Scene();

    // 相机
    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 0, 4);

    // 渲染器
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    document.body.appendChild(renderer.domElement);

    // 控件
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.minDistance = 1.5;
    controls.maxDistance = 10;
    controls.autoRotate = true;
    controls.autoRotateSpeed = 0.5;

    // 星空粒子
    const starsGeom = new THREE.BufferGeometry();
    const starsCount = 2000;
    const positions = new Float32Array(starsCount * 3);
    for (let i = 0; i < starsCount * 3; i++) {
      positions[i] = (Math.random() - 0.5) * 30;
    }
    starsGeom.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    const starsMat = new THREE.PointsMaterial({ color: 0xffffff, size: 0.02 });
    const stars = new THREE.Points(starsGeom, starsMat);
    scene.add(stars);

    // 地球
    const geometry = new THREE.SphereGeometry(1, 64, 64);

    // 使用纹理贴图(在线纹理)
    const textureLoader = new THREE.TextureLoader();
    const earthMap = textureLoader.load('https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg');
    const earthSpec = textureLoader.load('https://threejs.org/examples/textures/planets/earth_specular_2048.jpg');
    const earthBump = textureLoader.load('https://threejs.org/examples/textures/planets/earth_normal_2048.jpg');

    const material = new THREE.MeshPhongMaterial({
      map: earthMap,
      specularMap: earthSpec,
      bumpMap: earthBump,
      bumpScale: 0.05,
      specular: new THREE.Color('grey'),
      shininess: 10,
    });

    const earth = new THREE.Mesh(geometry, material);
    scene.add(earth);

    // 光照
    const ambientLight = new THREE.AmbientLight(0x333333);
    scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
    directionalLight.position.set(5, 3, 5);
    scene.add(directionalLight);

    // 动画循环
    function animate() {
      requestAnimationFrame(animate);
      stars.rotation.y += 0.0001;
      controls.update();
      renderer.render(scene, camera);
    }
    animate();

    // 响应式
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
  </script>
</body>
</html>

运行步骤

  1. 复制代码保存为 index.html
  2. 用 Live Server 打开(纹理需要 HTTP 协议加载)
  3. 或用 npx serve . 启动

预期输出

  • 3D 地球自动缓慢旋转
  • 鼠标拖拽旋转视角,滚轮缩放
  • 背景星空粒子缓慢移动
  • 光照渲染立体效果(海洋有反光)

毕设扩展方向

  • 添加标记点(城市标注)
  • 实现点击高亮某国家
  • 接入数据展示全球分布
  • 做成校园 3D 导览的基底

信息

路径
/tech-stacks/threejs/examples/Hello World - 旋转地球仪.md
更新时间
2026/5/30