Three.js 是构建 WebGL 3D 应用的强大工具,而结合 GIS(地理信息系统)后,可以实现炫酷的三维地理可视化效果。本教程将从基础入手,教你如何用 Three.js 打造一个简单的三维 GIS 应用。
我们希望实现以下功能:
mkdir threejs-gis
cd threejs-gis
npm init -y
npm install three
threejs-gis/
├── src/
│ ├── index.html # HTML 入口文件
│ ├── main.js # 主逻辑文件
│ ├── data/
│ │ └── world.geojson # 示例 GeoJSON 数据
├── package.json
└── node_modules/
在 src/index.html
中设置基础页面:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js GIStitle>
<style>
body { margin: 0; overflow: hidden; }
style>
head>
<body>
<canvas id="mapCanvas">canvas>
<script type="module" src="main.js">script>
body>
html>
在 src/main.js
中设置基础场景:
import * as THREE from 'three';
// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87ceeb); // 天空蓝背景
// 摄像机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 50, 100); // 初始位置
// 渲染器
const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('mapCanvas') });
renderer.setSize(window.innerWidth, window.innerHeight);
// 地板模拟地图
const planeGeometry = new THREE.PlaneGeometry(200, 200);
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x007b43, side: THREE.DoubleSide });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2; // 设置为水平面
scene.add(plane);
// 光源
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10, 20, 10);
scene.add(light);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
// 监听窗口大小变化
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
在 src/data/world.geojson
中添加示例数据:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]]
},
"properties": { "name": "Test Region" }
}
]
}
在 main.js
中使用 Three.js 绘制 GeoJSON 数据:
import { Shape, ShapeGeometry, Mesh, MeshStandardMaterial } from 'three';
async function loadGeoJSON(scene) {
const response = await fetch('./data/world.geojson');
const geojson = await response.json();
geojson.features.forEach((feature) => {
const shape = new Shape();
// 解析多边形坐标
const coords = feature.geometry.coordinates[0];
coords.forEach(([x, y], index) => {
if (index === 0) shape.moveTo(x, y);
else shape.lineTo(x, y);
});
// 创建 3D 几何体
const geometry = new ShapeGeometry(shape);
const material = new MeshStandardMaterial({ color: 0x228b22 });
const mesh = new Mesh(geometry, material);
mesh.rotation.x = -Math.PI / 2; // 设置为水平面
mesh.position.y = 0.1; // 抬高一点防止与地板重叠
scene.add(mesh);
});
}
// 加载并绘制 GeoJSON
loadGeoJSON(scene);
引入 OrbitControls 来实现交互控制:
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 平滑阻尼
实现点击地图显示区域信息:
renderer.domElement.addEventListener('click', (event) => {
const mouse = new THREE.Vector2(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1
);
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
console.log('Clicked on:', intersects[0].object.name);
}
});
mapshaper
)简化。通过本教程,你已经了解了如何结合 Three.js 和 GeoJSON 构建一个简单的 3D GIS 系统。接下来可以进一步拓展功能,比如:
需要更高级的功能或进一步优化?随时告诉我!