Three.js怎么读?WebGIS开发入门教程(附:GIS研习社源码)

编程与开发
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

《Three.js怎么读?WebGIS开发入门教程(附:GIS研习社源码)》这篇文章面向刚接触 WebGIS 三维开发的同学,先解决 Three.js 的读法和定位问题,再用一个最小可运行的三维地图场景,带你理解 Three.js 在 WebGIS 中到底负责什么、如何组织代码、如何和 GIS 数据结合。

引言:Three.js怎么读,以及它和WebGIS有什么关系

Three.js 通常读作 “Three JS”,中文交流里常被读成“思瑞 JS”或“Three 点 JS”。其中 Three 表示三维图形里的 3D,JS 表示 JavaScript。严格来说,Three.js 不是 GIS 软件,也不是地图引擎,而是一个基于 WebGL 的三维图形库。

在 WebGIS 开发中,Three.js 常用于补足传统二维地图的三维表达能力。例如:三维建筑、倾斜摄影模型、管线可视化、飞线效果、地形场景、点云浏览、空间分析结果三维展示等。

如果你已经会 Leaflet、OpenLayers 或 Mapbox GL JS,那么可以这样理解:地图引擎负责地图坐标、瓦片、交互和图层管理;Three.js 更擅长三维模型、材质、光照、相机和动画。

Three.js怎么读与WebGIS开发入门三维场景流程图
Three.js 在 WebGIS 中通常位于浏览器渲染层,用来表达三维场景、模型、光照和动画。

背景:为什么WebGIS开发会用到Three.js

很多 GIS 初学者第一次听到 Three.js,是因为项目里出现了“地图上叠加三维模型”“在地图中显示建筑白模”“做三维可视化大屏”这类需求。传统二维 WebGIS 能解决底图、矢量图层、属性查询和空间定位,但面对三维表达时会遇到几个明显限制。

  • 二维地图无法自然表达建筑高度、管线埋深、飞行轨迹高度等 Z 值信息。
  • 普通矢量样式难以表现真实光照、材质、阴影和模型细节。
  • 复杂动画、粒子、扫描线、流动线等效果更适合交给三维图形库处理。
  • 部分三维 GIS 数据格式需要更灵活的渲染控制。

Three.js 的价值就在这里:它降低了直接写 WebGL 的难度。开发者不需要从着色器、矩阵计算、缓冲区对象开始写起,而是可以用场景、相机、几何体、材质、光源这些更容易理解的对象搭建三维画面。

原理:Three.js入门必须理解的5个核心对象

学习 Three.js WebGIS 开发,不建议一开始就追求炫酷效果。先理解最小三维场景的组成,后面叠加 GIS 数据才不会迷路。

1. Scene:场景

Scene 可以理解为三维世界的容器。所有模型、线、点、光源,最终都要添加到场景里。对于 WebGIS 来说,一个城市三维场景、一个管线场景、一个地形场景,都可以看成一个 Scene。

2. Camera:相机

Camera 决定用户从哪里看、朝哪里看、视野有多大。常见的是 PerspectiveCamera,也就是透视相机,适合三维地图浏览和模型查看。

3. Renderer:渲染器

Renderer 负责把三维场景绘制到浏览器页面上。Three.js 常用 WebGLRenderer,它会调用浏览器的 WebGL 能力完成渲染。

4. Geometry 与 Material:几何体和材质

Geometry 表示形状,例如立方体、平面、球、线段、自定义网格。Material 表示外观,例如颜色、透明度、贴图、金属感、粗糙度等。在 GIS 场景中,建筑轮廓拉伸成三维楼块,本质上就是几何体加材质。

5. Controls:交互控制

Controls 用来实现鼠标旋转、缩放、平移等交互。入门阶段常用 OrbitControls。它不是 GIS 坐标系统的一部分,但对调试三维场景非常重要。

记住一句话:Three.js 的最小运行逻辑是“创建场景、创建相机、创建渲染器、添加对象、循环渲染”。WebGIS 只是把 GIS 数据和空间坐标加入了这个三维流程。

步骤:用Three.js搭建一个WebGIS三维入门场景

下面用一个最小示例说明 Three.js WebGIS 开发的基本结构。示例目标不是做完整地图平台,而是让你看清楚三维场景如何运行,以及 GIS 数据后续应接入到哪里。

步骤1:准备项目目录

建议新建一个简单目录,便于理解源码结构。

three-webgis-demo/
  index.html
  js/
    main.js

如果你使用 Vite、Vue、React 等工程化环境也可以,但入门阶段建议先用最小 HTML 页面跑通逻辑。

步骤2:创建HTML容器

<div id="map3d"></div>

页面中需要一个容器承载 Three.js 渲染结果。实际项目里,这个容器可以和二维地图容器叠加,也可以单独作为三维地图视图。

步骤3:初始化Three.js场景

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

const container = document.getElementById('map3d');

const scene = new THREE.Scene();
scene.background = new THREE.Color(0xf5f7fb);

const camera = new THREE.PerspectiveCamera(
  60,
  container.clientWidth / container.clientHeight,
  1,
  10000
);

camera.position.set(300, 300, 300);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

这段代码完成了 WebGIS 三维场景的基础框架。这里还没有地图坐标,也没有 GIS 数据,但已经具备显示三维对象的能力。

步骤4:添加一个模拟建筑白模

为了让 GIS 读者更容易理解,我们不用普通立方体,而是把它看成一个简化建筑物。

const buildingGeometry = new THREE.BoxGeometry(80, 120, 180);
const buildingMaterial = new THREE.MeshStandardMaterial({
  color: 0x4f8cff,
  roughness: 0.6,
  metalness: 0.1
});

const building = new THREE.Mesh(buildingGeometry, buildingMaterial);
building.position.set(0, 0, 90);
scene.add(building);

注意:Three.js 默认没有“米”“度”“经纬度”的概念。这里的 80、120、180 只是三维坐标单位。在真实 WebGIS 项目中,通常需要把经纬度坐标转换为平面坐标或局部坐标后再渲染。

步骤5:添加光源和地面参考

const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(200, 300, 400);
scene.add(directionalLight);

const gridHelper = new THREE.GridHelper(600, 20, 0x999999, 0dddddd);
scene.add(gridHelper);

光源决定模型是否有立体感。GridHelper 可以作为调试参考网格,类似 GIS 软件里的坐标参考背景。

步骤6:启动渲染循环

function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}

animate();

Three.js 的动画和交互依赖渲染循环。即使场景不动,只要需要鼠标旋转、缩放和平移,也应该保持循环渲染。

步骤7:处理窗口尺寸变化

window.addEventListener('resize', () => {
  camera.aspect = container.clientWidth / container.clientHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.clientWidth, container.clientHeight);
});

如果不处理窗口变化,页面缩放后会出现画面拉伸、比例错误或黑边问题。这是 Three.js WebGIS 入门项目里很常见的小坑。

步骤:GIS数据如何接入Three.js

Three.js 本身不直接理解 Shapefile、GeoPackage、PostGIS 表或 ArcGIS 服务。WebGIS 开发中通常需要先把 GIS 数据转换成浏览器容易读取的格式,再转为 Three.js 对象。

方式1:GeoJSON面数据拉伸成建筑

如果你有建筑轮廓 GeoJSON,可以读取 Polygon 坐标,把二维面转换为 Shape,再用 ExtrudeGeometry 按高度字段拉伸。

const height = feature.properties.height || 30;

// 伪代码:将GeoJSON坐标转换为Three.js局部坐标
const shape = new THREE.Shape();
coords.forEach((point, index) => {
  const local = lonLatToLocal(point[0], point[1]);
  if (index === 0) {
    shape.moveTo(local.x, local.y);
  } else {
    shape.lineTo(local.x, local.y);
  }
});

const geometry = new THREE.ExtrudeGeometry(shape, {
  depth: height,
  bevelEnabled: false
});

这里最关键的不是拉伸,而是 lonLatToLocal。经纬度不能直接当 Three.js 坐标使用,否则模型会变形、尺度异常或离原点过远。

方式2:加载GLTF或GLB三维模型

如果项目中已有三维模型,例如单体建筑、设备、桥梁、管廊构件,可以使用 GLTFLoader 加载 glTF 或 GLB 格式。

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

const loader = new GLTFLoader();

loader.load('/models/building.glb', (gltf) => {
  const model = gltf.scene;
  model.position.set(0, 0, 0);
  model.scale.set(1, 1, 1);
  scene.add(model);
});

glTF 更适合 Web 端传输和渲染。相比直接加载复杂原始模型,它通常体积更可控,也更符合浏览器三维渲染流程。

方式3:与二维地图叠加

实际 WebGIS 项目中,Three.js 经常和 Mapbox GL JS、OpenLayers 或 Leaflet 配合。常见架构有两种。

  • 二维地图作为底图,Three.js 透明画布叠加在上方。
  • 使用支持自定义图层的地图引擎,把 Three.js 场景嵌入地图渲染流程。

第一种更容易入门,但坐标同步、缩放同步和视角同步需要自己处理。第二种更适合工程项目,但对地图引擎和矩阵变换要求更高。

常见坑:Three.js WebGIS入门最容易踩的错误

坑1:把经纬度直接当Three.js坐标

经纬度是角度单位,不是长度单位。直接用经纬度作为 x、y 坐标,会导致距离、面积和模型比例都不可靠。正确做法是先投影到平面坐标,或以某个中心点建立局部坐标系。

坑2:模型距离原点太远导致抖动

浏览器三维渲染使用浮点数计算。当坐标值特别大时,模型可能出现抖动、闪烁、线条断裂等问题。WebGIS 三维场景常用“局部坐标原点”解决:以项目中心点为原点,其他点都转成相对坐标。

坑3:Z轴方向理解错误

Three.js 默认 Y 轴通常被理解为竖直方向,但很多 GIS 和三维模型流程中 Z 轴代表高度。项目中必须统一约定,否则建筑可能横着躺、模型旋转 90 度、管线方向错乱。

坑4:只关注效果,不控制数据量

WebGIS 三维场景最怕一次性加载过多几何体。建筑白模、点云、倾斜摄影、轨迹线都可能造成页面卡顿。需要考虑数据分块、按视野加载、模型简化、合并材质和实例化渲染。

坑5:没有处理坐标系说明

数据来自 EPSG:4326、EPSG:3857、本地投影坐标或 CAD 坐标时,处理方式完全不同。Three.js WebGIS 开发前必须确认数据坐标系,否则后续所有偏移问题都会变成猜谜。

方法比较:Three.js、Cesium、Mapbox GL JS该怎么选

工具 更适合的场景 优势 注意事项
Three.js 自定义三维效果、模型展示、三维可视化大屏 图形控制能力强,生态丰富,适合做复杂视觉效果 不自带完整 GIS 坐标、瓦片、地球和图层体系
Cesium 三维地球、3D Tiles、地形、倾斜摄影、全球尺度场景 GIS 三维能力完整,适合真实地理空间场景 自定义底层视觉效果时门槛较高
Mapbox GL JS 矢量瓦片地图、二维到轻三维地图、城市地图应用 地图样式能力强,交互体验好,适合 Web 地图产品 复杂三维模型和自由三维效果不如 Three.js 灵活
OpenLayers 传统 WebGIS、OGC 服务、专业二维图层管理 GIS 图层能力成熟,适合业务系统 三维能力通常需要外部库配合

如果你的目标是学习三维图形和 WebGIS 可视化效果,Three.js 是很好的入门选择。如果你的目标是做三维地球、倾斜摄影和大范围地形,Cesium 通常更直接。如果你的目标是二维地图业务系统,OpenLayers 或 Mapbox GL JS 可能更适合作为主地图框架。

检查清单:开始写Three.js WebGIS源码前先确认这些

  • 是否明确 Three.js 在项目中负责三维渲染,而不是完整 GIS 平台能力?
  • 数据坐标系是否已确认,例如 EPSG:4326、EPSG:3857 或本地投影?
  • 是否建立了局部坐标原点,避免大坐标导致精度问题?
  • 二维地图和 Three.js 叠加时,是否处理了缩放、平移、旋转和视角同步?
  • 模型格式是否适合 Web 端加载,例如 glTF 或 GLB?
  • 是否控制了模型面数、纹理大小、材质数量和同时加载的数据量?
  • 是否处理了浏览器窗口变化和设备像素比?
  • 是否为不同数据类型设计了加载失败、空数据和坐标异常的提示?

FAQ:Three.js怎么读与WebGIS开发常见问题

Three.js到底怎么读?

Three.js 一般读作 “Three JS”。中文语境中读成“思瑞 JS”也很常见。面试或技术交流时,说 “Three JS,一个基于 WebGL 的三维图形库”最清楚。

Three.js适合做完整的WebGIS地图系统吗?

不建议只用 Three.js 做完整 WebGIS 系统。它不提供成熟的地图投影、瓦片管理、OGC 服务接入和图层管理能力。更常见的做法是用 OpenLayers、Mapbox GL JS 或 Cesium 管理 GIS 能力,再用 Three.js 处理自定义三维效果。

Three.js能加载Shapefile吗?

Three.js 不能直接加载 Shapefile。通常需要先把 Shapefile 转成 GeoJSON、TopoJSON 或后端接口返回的 JSON 数据,再在前端转换为 Three.js 的点、线、面或模型对象。

Three.js和Cesium有什么区别?

Three.js 是通用三维图形库,适合自定义渲染效果。Cesium 是面向地理空间的三维地球平台,内置地球、地形、影像、3D Tiles 和相机控制。WebGIS 三维项目中,两者不是谁完全替代谁,而是看需求选择。

WebGIS开发入门应该先学Three.js还是先学地图框架?

如果你是 GIS 背景,建议先掌握 Web 地图基础,例如坐标系、瓦片、GeoJSON、OpenLayers 或 Mapbox GL JS,再学习 Three.js。这样你会更容易理解三维对象如何落到真实地理位置上。

GIS研习社源码适合怎么学习?

建议不要只复制运行结果,而是按模块阅读:先看场景初始化,再看相机和控制器,然后看数据转换,最后看模型或图层加载。每次只改一个参数,例如相机位置、建筑高度、材质颜色,这样更容易建立 Three.js WebGIS 开发的直觉。

结论:把Three.js当作WebGIS三维渲染工具来学

Three.js怎么读并不难,真正重要的是理解它在 WebGIS 开发中的位置:它负责三维图形表达,但不等于完整 GIS 引擎。入门时先跑通最小场景,再理解场景、相机、渲染器、几何体、材质和控制器,最后再接入 GeoJSON、三维模型或地图框架。

对于 GIS 学生和初级 WebGIS 开发者,最稳妥的学习路线是:先掌握二维 WebGIS 基础,再学习 Three.js 最小三维场景,然后补上坐标转换、局部坐标、模型加载和性能优化。这样写出来的源码不仅能动,也更接近真实项目。