three-tile
TypeScript icon, indicating that this package has built-in type declarations

0.5.1 • Public • Published

three-tile V0.5

郭江峰 hz_gjf@163.com SXMB

1 简介

three-tile 是一个基于 threejs 的轻量级三维瓦片地图框架,具有使用简单、资源占用少等优点,适用于基于 threejs 开发三维地图应用。

  • three-tile 本质上是一个动态 LOD 模型,核心代码与地图是无关的,适用范围并不仅限于地图,但最典型的应用还是三维地图。

  • three-tile 不是一个 GIS 框架,它并不提供图层管理、空间分析等 GIS 相关功能。正因为如此,它的核心可以做的很轻量级,能轻松集成到已有项目中。

  • three-tile 参考了大量开源 GIS 的开发思路,但仅仅是思路,除了数据源定义,未 copy 一行代码,更不是 Cesium、MapBox 等套壳。

免责声明:

  • 本框架不含任何地图数据,Example 中使用的地图均为直接调用第三方数据,使用中请遵循法律法规要求。
  • Example 中使用的图片和模型,均来自互联网,若涉及版权问题请通知我。

1.1 优点

  • 轻量级:地图以一个三维模型方式提供,不会对你的程序架构产生任何影响。
  • 依赖少:整个框架仅有 threejs(R152)一个依赖。
  • 速度快:对资源占用做极致优化,核显也能轻松跑到 60FPS。
  • 使用简单:熟悉 threejs 基本上没有学习成本。
  • 扩展性强:数据、模型、纹理、材质、渲染过程均能根据自己需要扩展和替换。

1.3 开发环境

  • 语言:TypeScript 100%
  • IDE: VSCode
  • 打包:Vite 4.0
  • 依赖:three^0.152

2 安装

建议使用 typescript 开发,原生 JavaScript 写的代码 BUG 防不胜防,至少使用 ES6。

2.1 直接引用

<script src="./three.js"></script>
<script src="./three-tile.umd.js"></script>

2.2 npm

npm i three-tile -S

https://www.npmjs.com/package/three-tile


3 使用

和一般 threejs 应用一样,初始化 threejs 三维场景后,将地图模型加入场景即可完成地图的显示。

TileMap 类是 three-tile 地图模型,它是一个 Mesh,按 threejs 的套路初始化场景,并将 TileMap 的实例加入场景即可。

为了便于使用,three-tile 还提供一个 GLViewer 类,它封装了场景初始化过程,一般可直接使用它进行初始化。但如果你熟悉 threejs,最好自己写,跟普通 threejs 程序并无太大差异。

3.1 约定和限制

  • 坐标轴:地图模型为东北上坐标系,即 X 轴指向东,Y 轴指向北,Z 轴指向上。与 threejs 默认坐标不同需要注意。
  • 坐标单位:角度单位为弧度,经纬度为度,3857 投影(默认)距离单位为公里,4326 投影距离单位为 0.01 度,高度单位均为公里。
  • 瓦片数据:内建的地图影像和地形数据均使用图片格式(jpg、png、webp 等),支持 3854 和 4326 投影,暂不支持矢量瓦片。
  • 瓦片属性:默认情况瓦片模型纹理透明属性开启,请注意渲染顺序。
  • 地图清晰度:清晰度与本框架无关,取决数据源精度。
  • 地图标注源:大部分国内厂商地图数据的地名、边界、道路有一定偏移,与地形无法完全匹配。
  • 地图 token:大部分厂商的地图数据需要申请开发 key 才能使用,three-tile 示例包含一些厂商的 token,访问的人多了厂商会封掉它们,使用者一定要自己申请(又不要钱)避免直接使用。

3.2 地图创建

一般应用,可使用 TileMap 的工厂方法 create 创建地图,用 GLViewer 初始化三维场景,并将地图加入场景。

import 方式:

import * as tt from "three-tile";

// 取得地图dom容器
const glContainer = document.querySelector<HTMLElement>("#map");
// 初始化三维场景(调用three-tile内置的初始化类)
const viewer = new tt.plugin.GLViewer(glContainer!);

// MapBoxToken 请更换为你自己申请的key
const MAPBOXKEY = "xxxxxxxxxx";

// mapbox 影像数据源
const mapBoxImgSource = new tt.plugin.MapBoxSource({
	token: MAPBOXKEY,
	dataType: "image",
	style: "mapbox.satellite",
});

// mapbox 高程数据源
export const mapBoxDemSource = new tt.plugin.MapBoxSource({
	token: MAPBOXKEY,
	dataType: "terrain-rgb",
	style: "mapbox.terrain-rgb",
	maxLevel: 15,
});

// 创建地图
const map = tt.TileMap.create({
	// 影像数据源
	imgSource: mapBoxImgSource,
	// 地形数据源
	demSource: mapBoxDemSource,
	// 地图投影中心经度
	centralMeridian: 90,
	// 最小缩放级别
	minLevel: 2,
	// 最大缩放级别
	maxLevel: 18,
});

// 将地图加入三维场景
viewer.scene.add(map);

浏览器引入方式:

<!DOCTYPE html>
<html lang="zh-cn">
	<head>
		<meta charset="utf-8" />
		<meta
			name="viewport"
			content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
		/>
		<title>three-tile</title>
	</head>
	<style>
		html,
		body {
			background-color: #333;
			height: 100%;
			width: 100%;
			padding: 0;
			margin: 0;
			display: flex;
		}
		#map {
			flex: 1;
		}
	</style>
	<body>
		<div id="map"></div>
		<script src="./three.js"></script>
		<script src="./three-tile/three-tile.umd.cjs"></script>
		<script>
			console.log("three-tile start!");

			// MapBoxToken 请更换为你自己申请的key
			const MAPBOXKEY =
				"pk.eyJ1Ijoic2hhbmUwMjIwNzIiLCJhIjoiY2p5amF6YnFiMDB0YjNkcGU1ZWxoMWl0NiJ9.TsmgK5-HJKWOE-DscbNbTA";

			// mapbox影像数据源
			const mapBoxImgSource = new tt.plugin.MapBoxSource({
				token: MAPBOXKEY,
				dataType: "image",
				style: "mapbox.satellite",
			});
			// mapbox地形数据源
			const mapBoxDemSource = new tt.plugin.MapBoxSource({
				token: MAPBOXKEY,
				dataType: "terrain-rgb",
				style: "mapbox.terrain-rgb",
				maxLevel: 15,
			});

			// 创建地图
			const map = tt.TileMap.create({
				// 影像数据源
				imgSource: mapBoxImgSource,
				// 地形数据源
				demSource: mapBoxDemSource,
				// 地图投影中心经度
				centralMeridian: 90,
				// 最小缩放级别
				minLevel: 2,
				// 最大缩放级别
				maxLevel: 18,
			});

			// 地图中心经纬度转为场景坐标
			const center = map.geo2pos(new THREE.Vector3(108.942, 34.2855));
			const container = document.querySelector("#map");
			const viewer = new tt.plugin.GLViewer(
				container,
				new THREE.Vector3(center.x, center.y, 0),
				new THREE.Vector3(center.x, center.y, 3e4),
			);

			viewer.scene.add(map);

			// 添加地图坐标轴
			const helper = new THREE.AxesHelper(1000);
			helper.position.set(center.x, center.y, 1);
			viewer.scene.add(helper);

			// 动画漫游到3500km高空
			(() => {
				const timer = setInterval(() => {
					const pos = viewer.camera.position;
					pos.z -= 500;
					pos.y -= 10;
					if (pos.z < 100) {
						clearInterval(timer);
					}
				}, 10);
			})();
		</script>
	</body>
</html>

3.3 三维场景

三维场景的初始化与 threejs 的没有太大区别,three-tile 内置一个 GLView 插件,实现三维场景初始化,能满足普通应用,有特殊要求的可以自行实现。需要以下部分需要注意:

  • 为了使地图坐标系与一般人类理解一致,地图坐标方向采用东(x)北(y)上(z)方向,即地面在 x-y 平面上,海拔高度在 z 轴。而 threejs 一般平面在 xz 平面上,高度为 y 轴,所以初始化时需要使场景默认 up 指向 z 轴,可添加:Object3D.DEFAULT_UP.set(0, 0, 1) 即可。如果你的应用不能调整 up 值,可以将地图旋转-π/2° 完成。
  • 地图添加光照才能显示。一般至少要有一个环境光,另外最好加一个直射光以通过地形法向量增强凹凸感。
  • 场景控制器一般应用可使用 threejs 内置的 MapControls,其它控制器如 OrbitControls、FlyControls、PointerLockControls、TransformControls、FirstPersonControls 都能完美支持。

更多使用方法见 example

Package Sidebar

Install

npm i three-tile

Weekly Downloads

5

Version

0.5.1

License

GPL V3

Unpacked Size

837 kB

Total Files

5

Last publish

Collaborators

  • guojf