Three.js 实现地球仪并标注城市教程(Trae实现)

本人最近在做一个全球地铁的导航网站——metrolinehub,于是就想做一个3D的旋转的地球,做3D的地球的话首先想到的是 Three.js。在三维可视化领域,Three.js 是一个强大且易用的 JavaScript 库,能够帮助开发者轻松创建各种炫酷的 3D 场景。本文将带你从零开始,使用 Three.js 实现一个精美的地球仪,并在地球仪上标注北京、上海、东京等城市。

在这里插入图片描述

网站

全球城市地铁地图: https://www.metrolinehub.com/zh

准备工作

在开始之前,你需要准备以下内容:

工具

  1. Trae工具:用于快速编写代码。
  2. three.js 库:可以从官方网站(https://threejs.org/ ) 下载,也可以使用 CDN 引入。

原理

  1. 就是使用 SphereGeometry 来创建一个球体,它定义了地球的基本形状,通过贴图实现地球的渲染,通过调整参数能控制球体的细分程度。
  2. 利用 requestAnimationFrame 函数创建一个动画循环,该函数会在浏览器准备好重绘页面时被调用。在每一帧中,通过修改地球网格对象的 rotation 属性(如 rotation.y )来改变地球的旋转角度,最后调用渲染器的 render 方法更新画面,从而实现地球持续旋转的视觉效果。

简单的说就是一个旋转的球,它可以是地球,也可以是篮球、足球等

一、项目搭建

在这里插入图片描述

首先,我们需要创建一个基本的 HTML 页面,并引入 Three.js 库。可以通过 CDN 引入 Three.js,在 HTML 文件的标签中添加以下代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r151/three.min.js"></script>

接着,在标签中创建一个用于渲染 3D 场景的容器元素,例如:

<div id="canvas-container"></div>

然后,在 HTML 文件末尾引入我们的 JavaScript 代码文件(假设文件名为script.js):

<script src="script.js"></script>

二、创建地球仪

在script.js文件中,开始编写创建地球仪的代码。首先,创建一个场景、相机和渲染器:

// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('canvas-container').appendChild(renderer.domElement);

接下来,创建地球的几何体和材质。我们使用SphereGeometry来创建球体几何体,并使用带有地球纹理的MeshStandardMaterial来赋予其地球外观。可以从网上下载合适的地球纹理图片,这里假设纹理图片文件名为earth.jpg:

// 创建地球几何体
const geometry = new THREE.SphereGeometry(2, 32, 32);
// 创建地球材质
const texture = new THREE.TextureLoader().load('earth.jpg');
const material = new THREE.MeshStandardMaterial({ map: texture });
// 创建地球模型
const earth = new THREE.Mesh(geometry, material);
scene.add(earth);

最后,在一个渲染循环函数中不断更新场景并渲染:

function animate() {
    requestAnimationFrame(animate);
    // 可以在这里添加地球旋转等动画逻辑
    earth.rotateY(0.01);
    renderer.render(scene, camera);
}
animate();

此时,运行 HTML 文件,你应该能看到一个旋转的地球仪。

三、准备城市数据

为了在地球仪上标注城市,我们需要准备城市的相关数据,包括城市名称、经纬度坐标等。可以将这些数据存储在一个 JavaScript 数组中,示例如下:

const cities = [
    { name: '北京', lat: 39.9042, lng: 116.4074 },
    { name: '上海', lat: 31.2304, lng: 121.4737 },
    { name: '东京', lat: 35.6895, lng: 139.6917 }
];

这里的经纬度坐标决定了城市在地球仪上的位置,需要根据实际情况准确获取。

四、在地球仪上标注城市

有了城市数据后,我们就可以将城市标注添加到地球仪上。首先,创建一个用于存放标注的组:

const cityMarkers = new THREE.Group();
scene.add(cityMarkers);

然后,遍历城市数据数组,为每个城市创建标注。标注可以使用Mesh或Sprite来实现,这里我们使用Sprite,它能始终面向相机,更适合做文字标注:

const fontLoader = new THREE.FontLoader();
fontLoader.load('https://cdnjs.cloudflare.com/ajax/libs/three.js/r151/fonts/helvetiker_regular.typeface.json', (font) => {
    cities.forEach((city) => {
        const textGeometry = new THREE.TextGeometry(city.name, {
            font: font,
            size: 0.2,
            height: 0.01
        });
        const textMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
        const textMesh = new THREE.Mesh(textGeometry, textMaterial);
        // 将经纬度坐标转换为三维空间中的位置
        const phi = (90 - city.lat) * Math.PI / 180;
        const theta = (city.lng - 180) * Math.PI / 180;
        const radius = 2.2; // 标注在地球表面外一定距离
        textMesh.position.x = radius * Math.sin(phi) * Math.cos(theta);
        textMesh.position.y = radius * Math.cos(phi);
        textMesh.position.z = radius * Math.sin(phi) * Math.sin(theta);
        cityMarkers.add(textMesh);
    });
});

上述代码中,首先加载了一个字体文件,然后为每个城市创建一个TextGeometry作为文字内容,设置好材质后创建Mesh。接着,通过经纬度坐标计算出城市在三维空间中的位置,并将标注添加到之前创建的cityMarkers组中。

五、优化与拓展

  1. 标注样式优化:可以为标注添加阴影、调整字体颜色和大小,使其更加美观醒目。

  2. 添加交互:可以添加鼠标悬停提示、点击跳转等交互功能,提升用户体验。例如,使用THREE.Raycaster实现鼠标点击检测,当点击到标注时弹出城市详细信息。

  3. 更多城市数据:可以从网络获取更多城市数据,丰富地球仪上的标注内容。

通过以上步骤,我们成功地使用 Three.js 实现了一个带有城市标注的地球仪。希望本文能帮助你在 Three.js 的学习和实践中有所收获,你可以根据自己的需求进一步拓展和完善这个项目。

在这里插入图片描述

其他文章

使用 Leaflet.js 生成北京地铁地图(Trae实现)

中国地铁导航
在这里插入图片描述

实现类似 `trae.cn` 首页的 3D 动态方块动画效果,可以使用现代 Web 技术结合 WebGL 或其封装库来完成。以下是一个较为完整的实现方案,涵盖了核心技术选型、实现步骤以及部分代码示例。 ### 技术选型 1. **Three.js**:这是目前最流行的基于 WebGL 的 3D 图形库,适合用于创建复杂的 3D 场景和动画。 2. **GSAP(GreenSock Animation Platform)**:用于实现高性能的动画控制,尤其适合与 Three.js 配合使用。 3. **HTML5 + CSS3**:用于页面结构和基础样式布局。 ### 实现步骤 1. **初始化 Three.js 场景** 创建一个基本的 3D 场景,包括相机、渲染器、场景对象等。 ```javascript // 初始化场景 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); ``` 2. **创建动态方块网格** 使用 `THREE.BoxGeometry` 创建多个立方体,通过 `THREE.Mesh` 将其添加到场景中。 ```javascript const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建多个立方体 const cubes = []; for (let i = 0; i < 100; i++) { const cube = new THREE.Mesh(geometry, material); cube.position.set(Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5); scene.add(cube); cubes.push(cube); } ``` 3. **添加动态动画效果** 使用 `requestAnimationFrame` 循环更新立方体的位置和旋转,实现动态变化。 ```javascript function animate() { requestAnimationFrame(animate); cubes.forEach((cube, index) => { cube.rotation.x += 0.01; cube.rotation.y += 0.01; cube.position.z = Math.sin(Date.now() * 0.001 + index) * 2; }); camera.position.z = 5; renderer.render(scene, camera); } animate(); ``` 4. **响应式布局与性能优化** 监听窗口大小变化调整渲染器尺寸,同时可以使用 `OrbitControls` 提供交互式视角控制。 ```javascript window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); ``` 5. **添加交互与视觉增强** 可以通过 `THREE.EffectComposer` 添加后期处理效果,如模糊、辉光等,提升视觉体验。 ### 进阶技巧 - **着色器编程**:使用自定义 `THREE.ShaderMaterial` 实现更复杂的表面效果。 - **性能优化**:使用 `THREE.InstancedMesh` 减少绘制调用,提高大量相同几何体的渲染性能。 - **粒子系统**:结合 `THREE.Points` 创建动态背景或特效。 ### 示例效果 通过上述代码可以实现一个包含多个动态变化立方体的 3D 场景,结合动画和交互控制,能够模拟类似 `trae.cn` 的视觉风格[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值