接上篇:
three-tile 是一个开源的轻量级三维瓦片库,它基于threejs使用typescript开发,提供一个三维地形模型,能轻松给你的应用增加三维瓦片地图。
项目地址:GitHub - sxguojf/three-tile: 3D tile map using threejs
示例地址:GitHub - sxguojf/three-tile-example: three-tile Examples
three-tile使用地图瓦片服务作为地图数据,包括影像数据和地形数据。
与大部分开源gis系统一样,three-tile并未绑定哪家地图服务,你可以任意选择各厂商瓦片地图服务,也可以自行部署离线瓦片服务,还可以自定义瓦片服务切片规则。
本节讲解如何使用主流场景的瓦片服务和自定义瓦片。
1. 使用three-tile内置的瓦片地图数据源
three-tile内置了mapbox、bing、arcgis、天地图、高德、腾讯等主流厂商的瓦片地图服务,这些地图可以直接使用,先定义数据源,然后将其传入地图:
// MapBoxToken 请更换为你自己申请的key
const MAPBOXKEY =
"pk.eyJ1Ijoic3ZjLW9rdGEtbWFwYm94LXN0YWZmLWFjY2VzcyIsImEiOiJjbG5sMnBoMm0xeWZzMmtyaWl0b2wyN2FuIn0.-zx1KP3Oy-7YzWcvhbv22Q";
// 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,
});
上面定义了一个影像数据源和一个地形数据源,都是mapbox家的。
代码比较简单,需要说明的是datatype参数,它用来标识数据瓦片数据的类型,程序运行时会根据此标识选择相应的加载器(Loader)加载解析创建瓦片模型。一般取值也就两种:
- image:影像数据,绝大多数瓦片均为此类型
- terrain-rgb:rgb格式的地形数据,是mapbox定义的一种地形瓦片格式。Mapbox Terrain-RGB v1 | Tilesets | Mapbox Docs | Mapbox
目前地形加载器只有两种,一种是mapbox的terrain-rgb格式,另一种是arcgis的lerc格式,cesium的Quantized-Mesh没搞定暂不支持。
其它厂家的数据也大同小异:
// Bing
export const bingSource = new BingSource({ style: "A,L" });
// 高德
export const gdImgSource = new GDSource({ style: "6" });
export const gdImgLabelSource = new GDSource({ style: "8" });
// arcgis
export const arcGisSource = new ArcGisSource();
// export const arcGisDemSource = new ArcGisDemSource();
export const arcGisCiaSource = new ArcGisSource({
style: "Reference/World_Boundaries_and_Places",
});
创建完成后,将数据源传入TileMap
// 影像数据源
const imgSource = mapBoxImgSource;
// 地形数据源
const demSource = mapBoxDemSource;
// 创建地图对象
const map = new tt.TileMap({
// 影像数据源
imgSource: imgSource,
// 高程数据源
demSource: demSource,
// 地图投影中央经线经度
lon0: 90,
// 最小缩放级别
minLevel: 2,
// 最大缩放级别
maxLevel: 20,
});
imgSource还可以是一个数组,它会将多层影像数据叠加混合。
你也可以在运行时动态改变数据源:
setGeoq: () => {
map.imgSource = [new tt.plugin.GeoqSource()];
map.reload();
},
2. 自定义数据源
自定义数据源,跟leaflet、cesium等类似,一般只需要填入瓦片url模板:
document.querySelector("#arcgis")?.addEventListener("click", () => {
// 用Source的create方法创建数据源
const imgSource = tt.TileSource.create({
dataType: "image",
attribution: "ArcGIS",
url: "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
});
map.imgSource = imgSource;
map.reload();
});
document.querySelector("#gd")?.addEventListener("click", () => {
// 创建Source类实例生成数据源(跟工厂方法一样)
const p1 = new tt.TileSource({
url: "https://webst04.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
attribution: "GAODE",
dataType: "image",
});
const p2 = new tt.TileSource({
url: "https://webst04.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}",
attribution: "GAODE",
dataType: "image",
});
// map.imgSource可以是一个数组
map.imgSource = [p1, p2];
map.reload();
});
瓦片xyz规则为google方案,如果其它规则,可继承TileSource,覆盖TileSource.getUrl函数,自行计算返回url,如bing瓦片的部分代码:
/**
* Bing datasource
*/
export class BingSource extends TileSource {
public dataType: string = "image";
public attribution = "Bing[GS(2021)1731号]";
public style: string = "A";
public mkt: string = "zh-CN";
public subdomains = "123";
public constructor(options?: BingSourceOptions) {
super(options);
Object.assign(this, options);
}
public getUrl(x: number, y: number, z: number): string {
const key = quadKey(z, x, y);
return `https://t${this.s}.dynamic.tiles.ditu.live.com/comp/ch/${key}?mkt=${this.mkt}&ur=CN&it=${this.style}&n=z&og=804&cstl=vb`;
}
}
3. 自定义瓦片范围
和其它gis软件类型,你可能想加载自己的一小片区域瓦片,可以在定义数据源时,通过bounds参数控制瓦片范围:
setBoundsTile: () => {
const bounds: [number, number, number, number] = [
108.60157012939453, 30.64670562744141, 108.65313291549683, 30.69008231163025,
];
const urlPrefix = "http://127.0.0.1:5500/testSource";
const imgSource = tt.TileSource.create({
url: urlPrefix + "/img/{z}/{x}/{y}.png",
bounds,
minLevel: 0,
maxLevel: 16,
});
const demSource = tt.TileSource.create({
dataType: "terrain-rgb",
url: urlPrefix + "/dem/{z}/{x}/{y}.png",
bounds,
minLevel: 5,
maxLevel: 15,
});
map.imgSource = [ms.arcGisSource, imgSource];
map.demSource = demSource;
// Move the camera to the bounds
viewer.controls.target.copy(map.localToWorld(map.geo2pos(new Vector3(108.627984, 30.66284, 0.0))));
viewer.camera.position.copy(map.localToWorld(map.geo2pos(new Vector3(108.627139, 30.64138, 3.309163))));
map.reload();
},
};
看似代码比较多,其实跟其它gis软件一样,推荐一个国外网站,有大量瓦片服务,不过老外的地图使用时需要小心。Leaflet Provider Demo (leaflet-extras.github.io)