@movk/maplibre 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +192 -0
- package/README.md +191 -0
- package/dist/module.d.mts +20 -0
- package/dist/module.d.ts +20 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +63 -0
- package/dist/runtime/components/CustomLayer.d.vue.ts +24 -0
- package/dist/runtime/components/CustomLayer.vue +23 -0
- package/dist/runtime/components/CustomLayer.vue.d.ts +24 -0
- package/dist/runtime/components/Layer.d.vue.ts +75 -0
- package/dist/runtime/components/Layer.vue +112 -0
- package/dist/runtime/components/Layer.vue.d.ts +75 -0
- package/dist/runtime/components/LayerGroup.d.vue.ts +25 -0
- package/dist/runtime/components/LayerGroup.vue +16 -0
- package/dist/runtime/components/LayerGroup.vue.d.ts +25 -0
- package/dist/runtime/components/LottieMarker.d.vue.ts +50 -0
- package/dist/runtime/components/LottieMarker.vue +31 -0
- package/dist/runtime/components/LottieMarker.vue.d.ts +50 -0
- package/dist/runtime/components/Map.d.vue.ts +84 -0
- package/dist/runtime/components/Map.vue +134 -0
- package/dist/runtime/components/Map.vue.d.ts +84 -0
- package/dist/runtime/components/Marker.d.vue.ts +54 -0
- package/dist/runtime/components/Marker.vue +86 -0
- package/dist/runtime/components/Marker.vue.d.ts +54 -0
- package/dist/runtime/components/Popup.d.vue.ts +30 -0
- package/dist/runtime/components/Popup.vue +33 -0
- package/dist/runtime/components/Popup.vue.d.ts +30 -0
- package/dist/runtime/components/Source.d.vue.ts +23 -0
- package/dist/runtime/components/Source.vue +44 -0
- package/dist/runtime/components/Source.vue.d.ts +23 -0
- package/dist/runtime/components/Tooltip.d.vue.ts +45 -0
- package/dist/runtime/components/Tooltip.vue +106 -0
- package/dist/runtime/components/Tooltip.vue.d.ts +45 -0
- package/dist/runtime/components/buffers/BufferCircle.d.vue.ts +27 -0
- package/dist/runtime/components/buffers/BufferCircle.vue +30 -0
- package/dist/runtime/components/buffers/BufferCircle.vue.d.ts +27 -0
- package/dist/runtime/components/buffers/BufferEllipse.d.vue.ts +35 -0
- package/dist/runtime/components/buffers/BufferEllipse.vue +36 -0
- package/dist/runtime/components/buffers/BufferEllipse.vue.d.ts +35 -0
- package/dist/runtime/components/buffers/BufferLine.d.vue.ts +21 -0
- package/dist/runtime/components/buffers/BufferLine.vue +40 -0
- package/dist/runtime/components/buffers/BufferLine.vue.d.ts +21 -0
- package/dist/runtime/components/buffers/BufferPolygon.d.vue.ts +21 -0
- package/dist/runtime/components/buffers/BufferPolygon.vue +40 -0
- package/dist/runtime/components/buffers/BufferPolygon.vue.d.ts +21 -0
- package/dist/runtime/components/buffers/BufferSector.d.vue.ts +31 -0
- package/dist/runtime/components/buffers/BufferSector.vue +35 -0
- package/dist/runtime/components/buffers/BufferSector.vue.d.ts +31 -0
- package/dist/runtime/components/controls/AttributionControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/AttributionControl.vue +18 -0
- package/dist/runtime/components/controls/AttributionControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/FullscreenControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/FullscreenControl.vue +18 -0
- package/dist/runtime/components/controls/FullscreenControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/GeolocateControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/GeolocateControl.vue +18 -0
- package/dist/runtime/components/controls/GeolocateControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/NavigationControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/NavigationControl.vue +18 -0
- package/dist/runtime/components/controls/NavigationControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/ScaleControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/ScaleControl.vue +18 -0
- package/dist/runtime/components/controls/ScaleControl.vue.d.ts +24 -0
- package/dist/runtime/components/effects/AnimatedImage.d.vue.ts +28 -0
- package/dist/runtime/components/effects/AnimatedImage.vue +50 -0
- package/dist/runtime/components/effects/AnimatedImage.vue.d.ts +28 -0
- package/dist/runtime/components/effects/DiffusionCircle.d.vue.ts +44 -0
- package/dist/runtime/components/effects/DiffusionCircle.vue +47 -0
- package/dist/runtime/components/effects/DiffusionCircle.vue.d.ts +44 -0
- package/dist/runtime/components/effects/FlowBuilding.d.vue.ts +53 -0
- package/dist/runtime/components/effects/FlowBuilding.vue +64 -0
- package/dist/runtime/components/effects/FlowBuilding.vue.d.ts +53 -0
- package/dist/runtime/components/effects/GlowCircle.d.vue.ts +44 -0
- package/dist/runtime/components/effects/GlowCircle.vue +42 -0
- package/dist/runtime/components/effects/GlowCircle.vue.d.ts +44 -0
- package/dist/runtime/components/effects/GradientBuilding.d.vue.ts +25 -0
- package/dist/runtime/components/effects/GradientBuilding.vue +37 -0
- package/dist/runtime/components/effects/GradientBuilding.vue.d.ts +25 -0
- package/dist/runtime/components/effects/Migration.d.vue.ts +50 -0
- package/dist/runtime/components/effects/Migration.vue +90 -0
- package/dist/runtime/components/effects/Migration.vue.d.ts +50 -0
- package/dist/runtime/components/effects/Radar.d.vue.ts +32 -0
- package/dist/runtime/components/effects/Radar.vue +49 -0
- package/dist/runtime/components/effects/Radar.vue.d.ts +32 -0
- package/dist/runtime/components/effects/SpriteImage.d.vue.ts +41 -0
- package/dist/runtime/components/effects/SpriteImage.vue +67 -0
- package/dist/runtime/components/effects/SpriteImage.vue.d.ts +41 -0
- package/dist/runtime/components/effects/TextureBuilding.d.vue.ts +25 -0
- package/dist/runtime/components/effects/TextureBuilding.vue +39 -0
- package/dist/runtime/components/effects/TextureBuilding.vue.d.ts +25 -0
- package/dist/runtime/components/effects/Trail.d.vue.ts +44 -0
- package/dist/runtime/components/effects/Trail.vue +61 -0
- package/dist/runtime/components/effects/Trail.vue.d.ts +44 -0
- package/dist/runtime/components/effects/WaveCircle.d.vue.ts +44 -0
- package/dist/runtime/components/effects/WaveCircle.vue +55 -0
- package/dist/runtime/components/effects/WaveCircle.vue.d.ts +44 -0
- package/dist/runtime/components/effects/WindowBuilding.d.vue.ts +53 -0
- package/dist/runtime/components/effects/WindowBuilding.vue +61 -0
- package/dist/runtime/components/effects/WindowBuilding.vue.d.ts +53 -0
- package/dist/runtime/components/environment/Sky.d.vue.ts +21 -0
- package/dist/runtime/components/environment/Sky.vue +15 -0
- package/dist/runtime/components/environment/Sky.vue.d.ts +21 -0
- package/dist/runtime/components/environment/Temperature.d.vue.ts +47 -0
- package/dist/runtime/components/environment/Temperature.vue +41 -0
- package/dist/runtime/components/environment/Temperature.vue.d.ts +47 -0
- package/dist/runtime/components/environment/Terrain.d.vue.ts +34 -0
- package/dist/runtime/components/environment/Terrain.vue +47 -0
- package/dist/runtime/components/environment/Terrain.vue.d.ts +34 -0
- package/dist/runtime/components/extensions/DrawControl.d.vue.ts +0 -0
- package/dist/runtime/components/extensions/DrawControl.vue +168 -0
- package/dist/runtime/components/extensions/DrawControl.vue.d.ts +0 -0
- package/dist/runtime/components/extensions/TiandituLayer.d.vue.ts +20 -0
- package/dist/runtime/components/extensions/TiandituLayer.vue +26 -0
- package/dist/runtime/components/extensions/TiandituLayer.vue.d.ts +20 -0
- package/dist/runtime/components/extensions/WmsLayer.d.vue.ts +50 -0
- package/dist/runtime/components/extensions/WmsLayer.vue +39 -0
- package/dist/runtime/components/extensions/WmsLayer.vue.d.ts +50 -0
- package/dist/runtime/components/extensions/WmtsLayer.d.vue.ts +42 -0
- package/dist/runtime/components/extensions/WmtsLayer.vue +37 -0
- package/dist/runtime/components/extensions/WmtsLayer.vue.d.ts +42 -0
- package/dist/runtime/components/layers/BuildingLayer.d.vue.ts +28 -0
- package/dist/runtime/components/layers/BuildingLayer.vue +41 -0
- package/dist/runtime/components/layers/BuildingLayer.vue.d.ts +28 -0
- package/dist/runtime/components/layers/ClusterLayer.d.vue.ts +55 -0
- package/dist/runtime/components/layers/ClusterLayer.vue +86 -0
- package/dist/runtime/components/layers/ClusterLayer.vue.d.ts +55 -0
- package/dist/runtime/components/layers/ImageLayer.d.vue.ts +21 -0
- package/dist/runtime/components/layers/ImageLayer.vue +25 -0
- package/dist/runtime/components/layers/ImageLayer.vue.d.ts +21 -0
- package/dist/runtime/components/layers/RasterLayer.d.vue.ts +35 -0
- package/dist/runtime/components/layers/RasterLayer.vue +34 -0
- package/dist/runtime/components/layers/RasterLayer.vue.d.ts +35 -0
- package/dist/runtime/components/layers/VideoLayer.d.vue.ts +28 -0
- package/dist/runtime/components/layers/VideoLayer.vue +38 -0
- package/dist/runtime/components/layers/VideoLayer.vue.d.ts +28 -0
- package/dist/runtime/composables/defineMaplibreControl.d.ts +3 -0
- package/dist/runtime/composables/defineMaplibreControl.js +6 -0
- package/dist/runtime/composables/useFeatureState.d.ts +35 -0
- package/dist/runtime/composables/useFeatureState.js +76 -0
- package/dist/runtime/composables/useFrameIcon.d.ts +17 -0
- package/dist/runtime/composables/useFrameIcon.js +36 -0
- package/dist/runtime/composables/useMap.d.ts +3 -0
- package/dist/runtime/composables/useMap.js +9 -0
- package/dist/runtime/composables/useMapAnimation.d.ts +21 -0
- package/dist/runtime/composables/useMapAnimation.js +13 -0
- package/dist/runtime/composables/useMapExport.d.ts +34 -0
- package/dist/runtime/composables/useMapExport.js +35 -0
- package/dist/runtime/composables/useMaplibre.d.ts +6 -0
- package/dist/runtime/composables/useMaplibre.js +4 -0
- package/dist/runtime/composables/useMaplibreCamera.d.ts +15 -0
- package/dist/runtime/composables/useMaplibreCamera.js +32 -0
- package/dist/runtime/composables/useMaplibreDraw.d.ts +10 -0
- package/dist/runtime/composables/useMaplibreDraw.js +34 -0
- package/dist/runtime/composables/useMaplibreImage.d.ts +19 -0
- package/dist/runtime/composables/useMaplibreImage.js +33 -0
- package/dist/runtime/composables/useMeasure.d.ts +25 -0
- package/dist/runtime/composables/useMeasure.js +173 -0
- package/dist/runtime/domains/map/config.d.ts +7 -0
- package/dist/runtime/domains/map/config.js +13 -0
- package/dist/runtime/domains/map/context.d.ts +13 -0
- package/dist/runtime/domains/map/context.js +51 -0
- package/dist/runtime/domains/map/control.d.ts +4 -0
- package/dist/runtime/domains/map/control.js +28 -0
- package/dist/runtime/domains/map/create-map.d.ts +3 -0
- package/dist/runtime/domains/map/create-map.js +21 -0
- package/dist/runtime/domains/map/draw-context.d.ts +26 -0
- package/dist/runtime/domains/map/draw-context.js +73 -0
- package/dist/runtime/domains/map/draw-registry.d.ts +5 -0
- package/dist/runtime/domains/map/draw-registry.js +15 -0
- package/dist/runtime/domains/map/draw-toolbar.d.ts +15 -0
- package/dist/runtime/domains/map/draw-toolbar.js +52 -0
- package/dist/runtime/domains/map/draw.d.ts +4 -0
- package/dist/runtime/domains/map/draw.js +1 -0
- package/dist/runtime/domains/map/layer-group.d.ts +9 -0
- package/dist/runtime/domains/map/layer-group.js +1 -0
- package/dist/runtime/domains/map/registry.d.ts +4 -0
- package/dist/runtime/domains/map/registry.js +10 -0
- package/dist/runtime/domains/map/resolve.d.ts +7 -0
- package/dist/runtime/domains/map/resolve.js +7 -0
- package/dist/runtime/domains/map/style-effect.d.ts +6 -0
- package/dist/runtime/domains/map/style-effect.js +21 -0
- package/dist/runtime/draw-modes/index.d.ts +16 -0
- package/dist/runtime/draw-modes/index.js +32 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/plugins/config.d.ts +2 -0
- package/dist/runtime/plugins/config.js +6 -0
- package/dist/runtime/types/draw.d.ts +30 -0
- package/dist/runtime/types/draw.js +0 -0
- package/dist/runtime/types/index.d.ts +3 -0
- package/dist/runtime/types/index.js +0 -0
- package/dist/runtime/types/map.d.ts +45 -0
- package/dist/runtime/types/map.js +0 -0
- package/dist/runtime/types/tianditu.d.ts +247 -0
- package/dist/runtime/types/tianditu.js +0 -0
- package/dist/runtime/utils/animated-image.d.ts +13 -0
- package/dist/runtime/utils/animated-image.js +47 -0
- package/dist/runtime/utils/buffer.d.ts +24 -0
- package/dist/runtime/utils/buffer.js +13 -0
- package/dist/runtime/utils/building-effects.d.ts +73 -0
- package/dist/runtime/utils/building-effects.js +50 -0
- package/dist/runtime/utils/building.d.ts +53 -0
- package/dist/runtime/utils/building.js +26 -0
- package/dist/runtime/utils/cluster.d.ts +24 -0
- package/dist/runtime/utils/cluster.js +42 -0
- package/dist/runtime/utils/coordinate.d.ts +12 -0
- package/dist/runtime/utils/coordinate.js +44 -0
- package/dist/runtime/utils/draw-theme.d.ts +47 -0
- package/dist/runtime/utils/draw-theme.js +39 -0
- package/dist/runtime/utils/effects.d.ts +34 -0
- package/dist/runtime/utils/effects.js +78 -0
- package/dist/runtime/utils/events.d.ts +6 -0
- package/dist/runtime/utils/events.js +20 -0
- package/dist/runtime/utils/frame-icon.d.ts +27 -0
- package/dist/runtime/utils/frame-icon.js +45 -0
- package/dist/runtime/utils/geometry.d.ts +5 -0
- package/dist/runtime/utils/geometry.js +41 -0
- package/dist/runtime/utils/heatmap.d.ts +36 -0
- package/dist/runtime/utils/heatmap.js +30 -0
- package/dist/runtime/utils/layer.d.ts +13 -0
- package/dist/runtime/utils/layer.js +17 -0
- package/dist/runtime/utils/logger.d.ts +2 -0
- package/dist/runtime/utils/logger.js +2 -0
- package/dist/runtime/utils/measure.d.ts +4 -0
- package/dist/runtime/utils/measure.js +8 -0
- package/dist/runtime/utils/sprite.d.ts +31 -0
- package/dist/runtime/utils/sprite.js +23 -0
- package/dist/runtime/utils/tianditu-administrative.d.ts +3 -0
- package/dist/runtime/utils/tianditu-administrative.js +48 -0
- package/dist/runtime/utils/tianditu-client.d.ts +30 -0
- package/dist/runtime/utils/tianditu-client.js +17 -0
- package/dist/runtime/utils/tianditu-geocoder.d.ts +5 -0
- package/dist/runtime/utils/tianditu-geocoder.js +37 -0
- package/dist/runtime/utils/tianditu-request.d.ts +20 -0
- package/dist/runtime/utils/tianditu-request.js +42 -0
- package/dist/runtime/utils/tianditu-route.d.ts +3 -0
- package/dist/runtime/utils/tianditu-route.js +40 -0
- package/dist/runtime/utils/tianditu-search.d.ts +15 -0
- package/dist/runtime/utils/tianditu-search.js +183 -0
- package/dist/runtime/utils/tianditu.d.ts +21 -0
- package/dist/runtime/utils/tianditu.js +26 -0
- package/dist/runtime/utils/wms.d.ts +43 -0
- package/dist/runtime/utils/wms.js +30 -0
- package/dist/runtime/utils/wmts.d.ts +35 -0
- package/dist/runtime/utils/wmts.js +29 -0
- package/dist/types.d.mts +5 -0
- package/dist/unplugin.d.mts +30 -0
- package/dist/unplugin.d.ts +30 -0
- package/dist/unplugin.mjs +53 -0
- package/dist/vite.d.mts +7 -0
- package/dist/vite.d.ts +7 -0
- package/dist/vite.mjs +11 -0
- package/dist/vue-plugin.d.mts +9 -0
- package/dist/vue-plugin.d.ts +9 -0
- package/dist/vue-plugin.mjs +9 -0
- package/package.json +174 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getJson, TIANDITU_ENDPOINTS, TiandituError } from "./tianditu-request.js";
|
|
2
|
+
function parseWktMultiPolygon(wkt) {
|
|
3
|
+
const inner = wkt.replace(/^\s*MULTIPOLYGON\s*\(\(\(/i, "").replace(/\)\)\)\s*$/, "");
|
|
4
|
+
return inner.split(/\)\)\s*,\s*\(\(/).map(
|
|
5
|
+
(polygon) => polygon.split(/\)\s*,\s*\(/).map(
|
|
6
|
+
(ring) => ring.split(",").map((pair) => {
|
|
7
|
+
const [lng, lat] = pair.trim().split(/\s+/).map(Number);
|
|
8
|
+
return [lng, lat];
|
|
9
|
+
})
|
|
10
|
+
)
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
function centerPoint(center) {
|
|
14
|
+
return [center.lng, center.lat];
|
|
15
|
+
}
|
|
16
|
+
function toDivision(district, includeBoundary) {
|
|
17
|
+
const division = {
|
|
18
|
+
name: district.name,
|
|
19
|
+
code: district.gb,
|
|
20
|
+
level: district.level,
|
|
21
|
+
center: centerPoint(district.center)
|
|
22
|
+
};
|
|
23
|
+
if (includeBoundary && district.boundary) {
|
|
24
|
+
division.boundary = { type: "MultiPolygon", coordinates: parseWktMultiPolygon(district.boundary) };
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(district.children)) {
|
|
27
|
+
division.children = district.children.map((child) => ({
|
|
28
|
+
name: child.name,
|
|
29
|
+
code: child.gb,
|
|
30
|
+
level: child.level,
|
|
31
|
+
center: centerPoint(child.center)
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
return division;
|
|
35
|
+
}
|
|
36
|
+
export async function administrative(keyword, options, tk) {
|
|
37
|
+
const includeBoundary = options.boundary ?? true;
|
|
38
|
+
const data = await getJson(TIANDITU_ENDPOINTS.administrative, {
|
|
39
|
+
keyword,
|
|
40
|
+
childLevel: String(options.childLevel ?? 0),
|
|
41
|
+
extensions: String(includeBoundary)
|
|
42
|
+
}, tk);
|
|
43
|
+
if (data.status !== void 0 && data.status !== 200) {
|
|
44
|
+
throw new TiandituError(data.status, data.message ?? "\u5929\u5730\u56FE\u884C\u653F\u533A\u5212\u67E5\u8BE2\u5931\u8D25");
|
|
45
|
+
}
|
|
46
|
+
const districts = data.data?.district;
|
|
47
|
+
return Array.isArray(districts) ? districts.map((district) => toDivision(district, includeBoundary)) : [];
|
|
48
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AdministrativeDivision, AdministrativeOptions, GeocodePoint, LocateOptions, Poi, ReverseGeocodeResult, RouteOptions, RouteResult, SearchParams, SearchResult } from '../types';
|
|
2
|
+
/** 天地图 Web 服务客户端;tk 在创建时注入一次,各方法无需重复传递。 */
|
|
3
|
+
export interface TiandituClient {
|
|
4
|
+
/** 地名搜索:一个入口覆盖 7 种 queryType,输出按 resultType 判别归一化。 */
|
|
5
|
+
search: (params: SearchParams) => Promise<SearchResult>;
|
|
6
|
+
/**
|
|
7
|
+
* 地名精确定位:适用于“把一个地标/地名解析为最佳匹配点”场景(与通用 search 不同,
|
|
8
|
+
* 未传 bounds 时会自动利用天地图返回的行政区建议二次收窄范围、并对同名结果做精确匹配优先排序)。
|
|
9
|
+
*/
|
|
10
|
+
locate: (keyword: string, options?: LocateOptions) => Promise<SearchResult>;
|
|
11
|
+
/** 周边 POI 搜索:给定中心点 + 半径检索附近兴趣点。 */
|
|
12
|
+
searchNearby: (keyword: string, center: [number, number], options?: {
|
|
13
|
+
radius?: number;
|
|
14
|
+
count?: number;
|
|
15
|
+
start?: number;
|
|
16
|
+
}) => Promise<Poi[]>;
|
|
17
|
+
/** 正地理编码:结构化地址→精确坐标点。 */
|
|
18
|
+
geocode: (address: string) => Promise<GeocodePoint | undefined>;
|
|
19
|
+
/** 逆地理编码:WGS84 坐标点→结构化地址。 */
|
|
20
|
+
reverseGeocode: (point: [number, number]) => Promise<ReverseGeocodeResult | undefined>;
|
|
21
|
+
/** 行政区划查询:中心点、边界轮廓、下级行政区。 */
|
|
22
|
+
administrative: (keyword: string, options?: AdministrativeOptions) => Promise<AdministrativeDivision[]>;
|
|
23
|
+
/** 驾车/步行路线规划:真实道路路径与距离/时长。 */
|
|
24
|
+
route: (origin: [number, number], destination: [number, number], options?: RouteOptions) => Promise<RouteResult>;
|
|
25
|
+
}
|
|
26
|
+
/** 创建天地图 Web 服务客户端,绑定 tk 后返回各接口方法。 */
|
|
27
|
+
export declare function createTianditu(options: {
|
|
28
|
+
tk: string;
|
|
29
|
+
}): TiandituClient;
|
|
30
|
+
export { TiandituError } from './tianditu-request';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { administrative } from "./tianditu-administrative.js";
|
|
2
|
+
import { geocode, reverseGeocode } from "./tianditu-geocoder.js";
|
|
3
|
+
import { route } from "./tianditu-route.js";
|
|
4
|
+
import { locate, search, searchNearby } from "./tianditu-search.js";
|
|
5
|
+
export function createTianditu(options) {
|
|
6
|
+
const { tk } = options;
|
|
7
|
+
return {
|
|
8
|
+
search: (params) => search(params, tk),
|
|
9
|
+
locate: (keyword, opts) => locate(keyword, opts ?? {}, tk),
|
|
10
|
+
searchNearby: (keyword, center, opts) => searchNearby(keyword, center, opts ?? {}, tk),
|
|
11
|
+
geocode: (address) => geocode(address, tk),
|
|
12
|
+
reverseGeocode: (point) => reverseGeocode(point, tk),
|
|
13
|
+
administrative: (keyword, opts) => administrative(keyword, opts ?? {}, tk),
|
|
14
|
+
route: (origin, destination, opts) => route(origin, destination, opts ?? {}, tk)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export { TiandituError } from "./tianditu-request.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { GeocodePoint, ReverseGeocodeResult } from '../types';
|
|
2
|
+
/** 正地理编码:把结构化地址(「北京市海淀区莲花池西路 28 号」)解析为精确坐标点,无结果或低置信度返回 undefined。 */
|
|
3
|
+
export declare function geocode(address: string, tk: string): Promise<GeocodePoint | undefined>;
|
|
4
|
+
/** 逆地理编码:把一个 WGS84 坐标点反查为结构化地址(「这是哪里」),无结果返回 undefined。 */
|
|
5
|
+
export declare function reverseGeocode(point: [number, number], tk: string): Promise<ReverseGeocodeResult | undefined>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getJson, TIANDITU_ENDPOINTS, TiandituError } from "./tianditu-request.js";
|
|
2
|
+
function assertNotError(status, msg) {
|
|
3
|
+
if (status === "404") throw new TiandituError("404", msg ?? "\u5929\u5730\u56FE\u5730\u7406\u7F16\u7801\u5931\u8D25");
|
|
4
|
+
}
|
|
5
|
+
const MIN_GEOCODE_SCORE = 60;
|
|
6
|
+
export async function geocode(address, tk) {
|
|
7
|
+
const data = await getJson(
|
|
8
|
+
TIANDITU_ENDPOINTS.geocoder,
|
|
9
|
+
{ ds: JSON.stringify({ keyWord: address }) },
|
|
10
|
+
tk
|
|
11
|
+
);
|
|
12
|
+
assertNotError(data.status, data.msg);
|
|
13
|
+
if (data.status !== "0" || !data.location) return void 0;
|
|
14
|
+
if (data.location.score !== void 0 && data.location.score < MIN_GEOCODE_SCORE) return void 0;
|
|
15
|
+
const location = [Number(data.location.lon), Number(data.location.lat)];
|
|
16
|
+
return { location, level: data.location.level || void 0, score: data.location.score };
|
|
17
|
+
}
|
|
18
|
+
export async function reverseGeocode(point, tk) {
|
|
19
|
+
const [lon, lat] = point;
|
|
20
|
+
const data = await getJson(
|
|
21
|
+
TIANDITU_ENDPOINTS.geocoder,
|
|
22
|
+
{ postStr: JSON.stringify({ lon, lat, ver: 1 }), type: "geocode" },
|
|
23
|
+
tk
|
|
24
|
+
);
|
|
25
|
+
assertNotError(data.status, data.msg);
|
|
26
|
+
if (data.status !== "0" || !data.result?.formatted_address) return void 0;
|
|
27
|
+
const c = data.result.addressComponent ?? {};
|
|
28
|
+
return {
|
|
29
|
+
formattedAddress: data.result.formatted_address,
|
|
30
|
+
// 直辖市 city 为空串,用 province 兜底
|
|
31
|
+
province: c.province || void 0,
|
|
32
|
+
city: c.city || c.province || void 0,
|
|
33
|
+
county: c.county || void 0,
|
|
34
|
+
road: c.road || void 0,
|
|
35
|
+
poi: c.poi || void 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const TIANDITU_ENDPOINTS: {
|
|
2
|
+
readonly search: "https://api.tianditu.gov.cn/v2/search";
|
|
3
|
+
readonly geocoder: "https://api.tianditu.gov.cn/geocoder";
|
|
4
|
+
readonly administrative: "https://api.tianditu.gov.cn/v2/administrative";
|
|
5
|
+
readonly drive: "https://api.tianditu.gov.cn/drive";
|
|
6
|
+
};
|
|
7
|
+
/** 天地图接口返回异常状态码时抛出;无数据/空结果不属于此类,按空值正常返回。 */
|
|
8
|
+
export declare class TiandituError extends Error {
|
|
9
|
+
/** 天地图状态码(检索 infocode、地理编码 status、行政区 status 或 HTTP 状态码) */
|
|
10
|
+
readonly code: number | string;
|
|
11
|
+
constructor(code: number | string, message: string);
|
|
12
|
+
}
|
|
13
|
+
/** 发起 GET 请求并按 JSON 解析。HTTP 非 2xx 抛 TiandituError。 */
|
|
14
|
+
export declare function getJson<T>(endpoint: string, params: Record<string, string>, tk: string): Promise<T>;
|
|
15
|
+
/** 发起 GET 请求并返回原始文本(驾车规划返回 XML)。HTTP 非 2xx 抛 TiandituError。 */
|
|
16
|
+
export declare function getText(endpoint: string, params: Record<string, string>, tk: string): Promise<string>;
|
|
17
|
+
/** 解析天地图 "经度,纬度" 字符串为坐标点(未做坐标系转换)。 */
|
|
18
|
+
export declare function parseLngLat(text: string): [number, number];
|
|
19
|
+
/** 将坐标点格式化为天地图 "经度,纬度" 字符串。 */
|
|
20
|
+
export declare function formatLngLat(point: [number, number]): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const TIANDITU_ENDPOINTS = {
|
|
2
|
+
search: "https://api.tianditu.gov.cn/v2/search",
|
|
3
|
+
// 正/逆地理编码共用此路径(无 /v2),通过 type/ds 参数区分
|
|
4
|
+
geocoder: "https://api.tianditu.gov.cn/geocoder",
|
|
5
|
+
administrative: "https://api.tianditu.gov.cn/v2/administrative",
|
|
6
|
+
// 驾车/步行规划,返回 XML
|
|
7
|
+
drive: "https://api.tianditu.gov.cn/drive"
|
|
8
|
+
};
|
|
9
|
+
export class TiandituError extends Error {
|
|
10
|
+
/** 天地图状态码(检索 infocode、地理编码 status、行政区 status 或 HTTP 状态码) */
|
|
11
|
+
code;
|
|
12
|
+
constructor(code, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "TiandituError";
|
|
15
|
+
this.code = code;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function buildUrl(endpoint, params, tk) {
|
|
19
|
+
const url = new URL(endpoint);
|
|
20
|
+
for (const [key, value] of Object.entries(params)) url.searchParams.set(key, value);
|
|
21
|
+
url.searchParams.set("tk", tk);
|
|
22
|
+
return url;
|
|
23
|
+
}
|
|
24
|
+
export async function getJson(endpoint, params, tk) {
|
|
25
|
+
const url = await buildUrl(endpoint, params, tk);
|
|
26
|
+
const res = await fetch(url);
|
|
27
|
+
if (!res.ok) throw new TiandituError(res.status, `\u5929\u5730\u56FE\u8BF7\u6C42\u5931\u8D25\uFF1AHTTP ${res.status}`);
|
|
28
|
+
return await res.json();
|
|
29
|
+
}
|
|
30
|
+
export async function getText(endpoint, params, tk) {
|
|
31
|
+
const url = await buildUrl(endpoint, params, tk);
|
|
32
|
+
const res = await fetch(url);
|
|
33
|
+
if (!res.ok) throw new TiandituError(res.status, `\u5929\u5730\u56FE\u8BF7\u6C42\u5931\u8D25\uFF1AHTTP ${res.status}`);
|
|
34
|
+
return await res.text();
|
|
35
|
+
}
|
|
36
|
+
export function parseLngLat(text) {
|
|
37
|
+
const [lng, lat] = text.trim().split(",").map(Number);
|
|
38
|
+
return [lng, lat];
|
|
39
|
+
}
|
|
40
|
+
export function formatLngLat(point) {
|
|
41
|
+
return `${point[0]},${point[1]}`;
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { formatLngLat, getText, parseLngLat, TIANDITU_ENDPOINTS, TiandituError } from "./tianditu-request.js";
|
|
2
|
+
const STYLE_MAP = {
|
|
3
|
+
"fastest": "0",
|
|
4
|
+
"shortest": "1",
|
|
5
|
+
"avoid-highway": "2",
|
|
6
|
+
"walking": "3"
|
|
7
|
+
};
|
|
8
|
+
function tag(xml, name) {
|
|
9
|
+
return new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(xml)?.[1];
|
|
10
|
+
}
|
|
11
|
+
export async function route(origin, destination, options, tk) {
|
|
12
|
+
const postStr = {
|
|
13
|
+
orig: formatLngLat(origin),
|
|
14
|
+
dest: formatLngLat(destination),
|
|
15
|
+
style: STYLE_MAP[options.mode ?? "fastest"]
|
|
16
|
+
};
|
|
17
|
+
if (options.waypoints?.length) {
|
|
18
|
+
postStr.mid = options.waypoints.map(formatLngLat).join(";");
|
|
19
|
+
}
|
|
20
|
+
const xml = await getText(TIANDITU_ENDPOINTS.drive, { postStr: JSON.stringify(postStr), type: "search" }, tk);
|
|
21
|
+
const routelatlon = tag(xml, "routelatlon");
|
|
22
|
+
if (!routelatlon) throw new TiandituError("no-route", "\u5929\u5730\u56FE\u672A\u8FD4\u56DE\u8DEF\u7EBF");
|
|
23
|
+
const path = {
|
|
24
|
+
type: "LineString",
|
|
25
|
+
coordinates: routelatlon.trim().replace(/;$/, "").split(";").map(parseLngLat)
|
|
26
|
+
};
|
|
27
|
+
const simple = /<simple>([\s\S]*?)<\/simple>/.exec(xml)?.[1] ?? "";
|
|
28
|
+
const guides = [...simple.matchAll(/<strguide>([\s\S]*?)<\/strguide>/g)].map((m) => m[1].trim());
|
|
29
|
+
const mapinfo = /<mapinfo>([\s\S]*?)<\/mapinfo>/.exec(xml)?.[1] ?? "";
|
|
30
|
+
const centerRaw = tag(mapinfo, "center");
|
|
31
|
+
const scaleRaw = tag(mapinfo, "scale");
|
|
32
|
+
return {
|
|
33
|
+
distanceKm: Number(tag(xml, "distance") ?? 0),
|
|
34
|
+
durationMinutes: Math.round(Number(tag(xml, "duration") ?? 0) / 60 * 10) / 10,
|
|
35
|
+
path,
|
|
36
|
+
summary: guides.length ? guides.join(" ") : void 0,
|
|
37
|
+
center: centerRaw ? parseLngLat(centerRaw) : void 0,
|
|
38
|
+
scale: scaleRaw ? Number(scaleRaw.trim()) : void 0
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LocateOptions, Poi, SearchParams, SearchResult } from '../types';
|
|
2
|
+
/** 地名搜索:一个入口覆盖天地图 7 种 queryType,输出按 resultType 判别归一化。 */
|
|
3
|
+
export declare function search(params: SearchParams, tk: string): Promise<SearchResult>;
|
|
4
|
+
/** 周边 POI 搜索:给定中心点 + 半径检索附近兴趣点,直接返回 POI 列表。 */
|
|
5
|
+
export declare function searchNearby(keyword: string, center: [number, number], options: {
|
|
6
|
+
radius?: number;
|
|
7
|
+
count?: number;
|
|
8
|
+
start?: number;
|
|
9
|
+
}, tk: string): Promise<Poi[]>;
|
|
10
|
+
/**
|
|
11
|
+
* 地名精确定位:全国范围模糊检索命中量大时排序质量会骤降(如关键词带省市前缀),
|
|
12
|
+
* 天地图会随结果附带一个行政区建议(suggestedDistrict);若调用方未显式指定 bounds,
|
|
13
|
+
* 自动用该建议行政区重新检索一次以收窄范围、提升排序精度,最终对同名结果做精确匹配优先排序。
|
|
14
|
+
*/
|
|
15
|
+
export declare function locate(keyword: string, options: LocateOptions, tk: string): Promise<SearchResult>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { formatLngLat, getJson, parseLngLat, TIANDITU_ENDPOINTS, TiandituError } from "./tianditu-request.js";
|
|
2
|
+
const CHINA_BOUNDS = [73.66, 3.86, 135.05, 53.55];
|
|
3
|
+
const QUERY_TYPE = {
|
|
4
|
+
normal: 1,
|
|
5
|
+
inView: 2,
|
|
6
|
+
nearby: 3,
|
|
7
|
+
polygon: 10,
|
|
8
|
+
district: 12,
|
|
9
|
+
category: 13,
|
|
10
|
+
statistics: 14
|
|
11
|
+
};
|
|
12
|
+
function boundsToMapBound(bounds) {
|
|
13
|
+
return `${bounds[0]},${bounds[1]},${bounds[2]},${bounds[3]}`;
|
|
14
|
+
}
|
|
15
|
+
function boundFromString(text) {
|
|
16
|
+
const [minx, miny, maxx, maxy] = text.split(",").map(Number);
|
|
17
|
+
return [minx, miny, maxx, maxy];
|
|
18
|
+
}
|
|
19
|
+
function toPoi(raw) {
|
|
20
|
+
return {
|
|
21
|
+
name: raw.name,
|
|
22
|
+
address: raw.address || void 0,
|
|
23
|
+
phone: raw.phone || void 0,
|
|
24
|
+
location: parseLngLat(raw.lonlat),
|
|
25
|
+
poiType: raw.poiType,
|
|
26
|
+
hotPointID: raw.hotPointID || void 0,
|
|
27
|
+
province: raw.province || void 0,
|
|
28
|
+
city: raw.city || void 0,
|
|
29
|
+
county: raw.county || void 0,
|
|
30
|
+
typeCode: raw.typeCode || void 0,
|
|
31
|
+
typeName: raw.typeName || void 0,
|
|
32
|
+
source: raw.source || void 0,
|
|
33
|
+
distance: raw.distance || void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function toStatistics(raw) {
|
|
37
|
+
return {
|
|
38
|
+
count: raw.count ?? 0,
|
|
39
|
+
adminCount: raw.adminCount ?? 0,
|
|
40
|
+
priorityCities: (raw.priorityCitys ?? []).map((city) => ({
|
|
41
|
+
name: city.name,
|
|
42
|
+
count: city.count ?? 0,
|
|
43
|
+
adminCode: String(city.adminCode ?? ""),
|
|
44
|
+
location: parseLngLat(city.lonlat)
|
|
45
|
+
}))
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function toArea(raw) {
|
|
49
|
+
return {
|
|
50
|
+
name: raw.name,
|
|
51
|
+
adminCode: String(raw.adminCode ?? ""),
|
|
52
|
+
level: raw.level ?? 0,
|
|
53
|
+
location: parseLngLat(raw.lonlat.replace(/[{}]/g, "")),
|
|
54
|
+
bound: raw.bound ? boundFromString(raw.bound) : void 0
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function toSuggestion(raw) {
|
|
58
|
+
return {
|
|
59
|
+
type: raw.type ?? 0,
|
|
60
|
+
keyword: raw.keyword ?? "",
|
|
61
|
+
admins: raw.admins ?? []
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function extractSuggestedDistrict(prompt) {
|
|
65
|
+
const admin = prompt?.find((p) => p.type === 4)?.admins?.[0];
|
|
66
|
+
return admin ? { name: admin.adminName, code: String(admin.adminCode) } : void 0;
|
|
67
|
+
}
|
|
68
|
+
function toLines(raw) {
|
|
69
|
+
return raw.map((line) => ({ name: line.name, uuid: line.uuid, stationNum: line.stationNum }));
|
|
70
|
+
}
|
|
71
|
+
function buildPostStr(params) {
|
|
72
|
+
const post = {
|
|
73
|
+
queryType: QUERY_TYPE[params.type],
|
|
74
|
+
start: params.start ?? 0,
|
|
75
|
+
count: params.count ?? 10
|
|
76
|
+
};
|
|
77
|
+
if ("keyword" in params && params.keyword) post.keyWord = params.keyword;
|
|
78
|
+
if (params.dataTypes) post.dataTypes = params.dataTypes;
|
|
79
|
+
if (params.show) post.show = params.show;
|
|
80
|
+
switch (params.type) {
|
|
81
|
+
case "normal":
|
|
82
|
+
post.mapBound = boundsToMapBound(params.bounds);
|
|
83
|
+
post.level = params.level;
|
|
84
|
+
if (params.specify) post.specify = params.specify;
|
|
85
|
+
break;
|
|
86
|
+
case "inView":
|
|
87
|
+
post.mapBound = boundsToMapBound(params.bounds);
|
|
88
|
+
post.level = params.level;
|
|
89
|
+
break;
|
|
90
|
+
case "nearby":
|
|
91
|
+
post.pointLonlat = formatLngLat(params.center);
|
|
92
|
+
post.queryRadius = params.radius;
|
|
93
|
+
break;
|
|
94
|
+
case "polygon":
|
|
95
|
+
post.polygon = params.polygon.map((point) => formatLngLat(point)).join(",");
|
|
96
|
+
break;
|
|
97
|
+
case "district":
|
|
98
|
+
post.specify = params.specify;
|
|
99
|
+
break;
|
|
100
|
+
case "category":
|
|
101
|
+
post.specify = params.specify;
|
|
102
|
+
post.mapBound = boundsToMapBound(params.bounds);
|
|
103
|
+
break;
|
|
104
|
+
case "statistics":
|
|
105
|
+
post.specify = params.specify;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
return post;
|
|
109
|
+
}
|
|
110
|
+
function normalize(data) {
|
|
111
|
+
switch (data.resultType) {
|
|
112
|
+
case 1:
|
|
113
|
+
return {
|
|
114
|
+
kind: "poi",
|
|
115
|
+
count: data.count ?? data.pois?.length ?? 0,
|
|
116
|
+
pois: (data.pois ?? []).map(toPoi),
|
|
117
|
+
suggestedDistrict: extractSuggestedDistrict(data.prompt)
|
|
118
|
+
};
|
|
119
|
+
case 2:
|
|
120
|
+
return { kind: "statistics", statistics: toStatistics(data.statistics ?? {}) };
|
|
121
|
+
case 3:
|
|
122
|
+
if (data.area) return { kind: "area", area: toArea(data.area) };
|
|
123
|
+
break;
|
|
124
|
+
case 4:
|
|
125
|
+
if (data.prompt?.[0]) return { kind: "suggestion", suggestion: toSuggestion(data.prompt[0]) };
|
|
126
|
+
break;
|
|
127
|
+
case 5:
|
|
128
|
+
return { kind: "line", lines: toLines(data.lineData ?? []) };
|
|
129
|
+
}
|
|
130
|
+
const info = data.status?.infocode;
|
|
131
|
+
if (info !== void 0 && info !== 1e3 && info !== 3001) {
|
|
132
|
+
throw new TiandituError(info, data.status?.cndesc ?? "\u5929\u5730\u56FE\u68C0\u7D22\u5931\u8D25");
|
|
133
|
+
}
|
|
134
|
+
return { kind: "empty" };
|
|
135
|
+
}
|
|
136
|
+
function normalizeCategories(data) {
|
|
137
|
+
const categories = Object.entries(data).map(([name, raw]) => ({
|
|
138
|
+
name,
|
|
139
|
+
count: raw.count ?? 0,
|
|
140
|
+
pois: (raw.pois ?? []).map(toPoi)
|
|
141
|
+
}));
|
|
142
|
+
return { kind: "categories", categories };
|
|
143
|
+
}
|
|
144
|
+
export async function search(params, tk) {
|
|
145
|
+
const data = await getJson(
|
|
146
|
+
TIANDITU_ENDPOINTS.search,
|
|
147
|
+
{ postStr: JSON.stringify(buildPostStr(params)), type: "query" },
|
|
148
|
+
tk
|
|
149
|
+
);
|
|
150
|
+
return "resultType" in data || "status" in data ? normalize(data) : normalizeCategories(data);
|
|
151
|
+
}
|
|
152
|
+
export async function searchNearby(keyword, center, options, tk) {
|
|
153
|
+
const result = await search({
|
|
154
|
+
type: "nearby",
|
|
155
|
+
keyword,
|
|
156
|
+
center,
|
|
157
|
+
radius: options.radius ?? 5e3,
|
|
158
|
+
count: options.count,
|
|
159
|
+
start: options.start
|
|
160
|
+
}, tk);
|
|
161
|
+
return result.kind === "poi" ? result.pois : [];
|
|
162
|
+
}
|
|
163
|
+
function prioritizeExactMatch(pois, keyword) {
|
|
164
|
+
return [...pois].sort((a, b) => Number(b.name === keyword) - Number(a.name === keyword));
|
|
165
|
+
}
|
|
166
|
+
export async function locate(keyword, options, tk) {
|
|
167
|
+
const autoNarrow = !options.bounds;
|
|
168
|
+
const first = await search({
|
|
169
|
+
type: "normal",
|
|
170
|
+
keyword,
|
|
171
|
+
bounds: options.bounds ?? CHINA_BOUNDS,
|
|
172
|
+
level: options.level ?? 10,
|
|
173
|
+
count: options.count
|
|
174
|
+
}, tk);
|
|
175
|
+
if (first.kind !== "poi") return first;
|
|
176
|
+
if (autoNarrow && first.suggestedDistrict && first.pois.length > 0) {
|
|
177
|
+
const narrowed = await search({ type: "district", specify: first.suggestedDistrict.code, keyword, count: options.count }, tk);
|
|
178
|
+
if (narrowed.kind === "poi" && narrowed.pois.length > 0) {
|
|
179
|
+
return { ...narrowed, pois: prioritizeExactMatch(narrowed.pois, keyword) };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return { ...first, pois: prioritizeExactMatch(first.pois, keyword) };
|
|
183
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RasterSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
2
|
+
/** 天地图图层类型:vec 矢量底图、img 影像底图、ter 地形、cva 矢量注记、cia 影像注记、cta 地形注记 */
|
|
3
|
+
export type TiandituLayerType = 'vec' | 'img' | 'ter' | 'cva' | 'cia' | 'cta';
|
|
4
|
+
/** 取底图对应的注记图层类型;注记类型自身或无对应时返回 undefined。 */
|
|
5
|
+
export declare function tiandituAnnotationFor(base: TiandituLayerType): TiandituLayerType | undefined;
|
|
6
|
+
export interface TiandituSourceOptions {
|
|
7
|
+
/** 天地图 token(tk);缺省时回退到运行时配置 maplibre.tk */
|
|
8
|
+
tk?: string;
|
|
9
|
+
/**
|
|
10
|
+
* 瓦片尺寸
|
|
11
|
+
* @defaultValue 256
|
|
12
|
+
*/
|
|
13
|
+
tileSize?: number;
|
|
14
|
+
/**
|
|
15
|
+
* 子域名数量(t0..t{n-1})
|
|
16
|
+
* @defaultValue 8
|
|
17
|
+
*/
|
|
18
|
+
subdomains?: number;
|
|
19
|
+
}
|
|
20
|
+
/** 生成天地图球面墨卡托(EPSG:3857)栅格数据源规格,可直接用于 MaplibreSource。 */
|
|
21
|
+
export declare function tiandituRasterSource(layer: TiandituLayerType, options?: TiandituSourceOptions): RasterSourceSpecification;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getMaplibreConfig } from "../domains/map/config.js";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
import { wmtsRasterSource } from "./wmts.js";
|
|
4
|
+
const ANNOTATION_MAP = {
|
|
5
|
+
vec: "cva",
|
|
6
|
+
img: "cia",
|
|
7
|
+
ter: "cta"
|
|
8
|
+
};
|
|
9
|
+
export function tiandituAnnotationFor(base) {
|
|
10
|
+
return ANNOTATION_MAP[base];
|
|
11
|
+
}
|
|
12
|
+
export function tiandituRasterSource(layer, options = {}) {
|
|
13
|
+
const tk = options.tk ?? getMaplibreConfig().tk;
|
|
14
|
+
if (!tk) logger.warn("Tianditu token (tk) is missing; tiles may fail to load.");
|
|
15
|
+
const count = options.subdomains ?? 8;
|
|
16
|
+
const subdomains = Array.from({ length: count }, (_, i) => String(i));
|
|
17
|
+
return wmtsRasterSource({
|
|
18
|
+
url: `https://t{s}.tianditu.gov.cn/${layer}_w/wmts`,
|
|
19
|
+
layer,
|
|
20
|
+
tileMatrixSet: "w",
|
|
21
|
+
subdomains,
|
|
22
|
+
tileSize: options.tileSize ?? 256,
|
|
23
|
+
attribution: "\xA9 \u5929\u5730\u56FE",
|
|
24
|
+
params: { tk: tk ?? "" }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { RasterSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
2
|
+
export interface WmsSourceOptions {
|
|
3
|
+
/** WMS 服务基础地址(GetMap 端点) */
|
|
4
|
+
url: string;
|
|
5
|
+
/** 图层 LAYERS(逗号分隔多层) */
|
|
6
|
+
layers: string;
|
|
7
|
+
/**
|
|
8
|
+
* WMS 版本;1.3.0 用 CRS、否则用 SRS
|
|
9
|
+
* @defaultValue '1.1.1'
|
|
10
|
+
*/
|
|
11
|
+
version?: string;
|
|
12
|
+
/**
|
|
13
|
+
* 图片格式 FORMAT
|
|
14
|
+
* @defaultValue 'image/png'
|
|
15
|
+
*/
|
|
16
|
+
format?: string;
|
|
17
|
+
/**
|
|
18
|
+
* 是否透明 TRANSPARENT
|
|
19
|
+
* @defaultValue true
|
|
20
|
+
*/
|
|
21
|
+
transparent?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* 样式 STYLES
|
|
24
|
+
* @defaultValue ''
|
|
25
|
+
*/
|
|
26
|
+
styles?: string;
|
|
27
|
+
/**
|
|
28
|
+
* 坐标参考系
|
|
29
|
+
* @defaultValue 'EPSG:3857'
|
|
30
|
+
*/
|
|
31
|
+
crs?: string;
|
|
32
|
+
/**
|
|
33
|
+
* 瓦片尺寸(WIDTH/HEIGHT)
|
|
34
|
+
* @defaultValue 256
|
|
35
|
+
*/
|
|
36
|
+
tileSize?: number;
|
|
37
|
+
/** 版权信息 */
|
|
38
|
+
attribution?: string;
|
|
39
|
+
/** 透传查询参数 */
|
|
40
|
+
params?: Record<string, string | undefined>;
|
|
41
|
+
}
|
|
42
|
+
/** 构造 WMS GetMap 栅格数据源规格;maplibre 用 {bbox-epsg-3857} 占位符按瓦片请求。 */
|
|
43
|
+
export declare function wmsRasterSource(options: WmsSourceOptions): RasterSourceSpecification;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function wmsRasterSource(options) {
|
|
2
|
+
const version = options.version ?? "1.1.1";
|
|
3
|
+
const crs = options.crs ?? "EPSG:3857";
|
|
4
|
+
const size = options.tileSize ?? 256;
|
|
5
|
+
const crsKey = version === "1.3.0" ? "CRS" : "SRS";
|
|
6
|
+
const query = /* @__PURE__ */ new Map([
|
|
7
|
+
["SERVICE", "WMS"],
|
|
8
|
+
["REQUEST", "GetMap"],
|
|
9
|
+
["VERSION", version],
|
|
10
|
+
["LAYERS", options.layers],
|
|
11
|
+
["STYLES", options.styles ?? ""],
|
|
12
|
+
["FORMAT", options.format ?? "image/png"],
|
|
13
|
+
["TRANSPARENT", String(options.transparent ?? true).toUpperCase()],
|
|
14
|
+
[crsKey, crs],
|
|
15
|
+
["WIDTH", String(size)],
|
|
16
|
+
["HEIGHT", String(size)],
|
|
17
|
+
["BBOX", "{bbox-epsg-3857}"]
|
|
18
|
+
]);
|
|
19
|
+
for (const [key, value] of Object.entries(options.params ?? {})) {
|
|
20
|
+
if (value !== void 0) query.set(key, value);
|
|
21
|
+
}
|
|
22
|
+
const qs = Array.from(query, ([k, v]) => `${k}=${v}`).join("&");
|
|
23
|
+
const url = `${options.url}${options.url.includes("?") ? "&" : "?"}${qs}`;
|
|
24
|
+
return {
|
|
25
|
+
type: "raster",
|
|
26
|
+
tiles: [url],
|
|
27
|
+
tileSize: size,
|
|
28
|
+
...options.attribution ? { attribution: options.attribution } : {}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RasterSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
2
|
+
export interface WmtsSourceOptions {
|
|
3
|
+
/** WMTS 服务基础地址(GetTile 端点);含 {s} 时配合 subdomains 展开多 host */
|
|
4
|
+
url: string;
|
|
5
|
+
/** 图层标识 LAYER */
|
|
6
|
+
layer: string;
|
|
7
|
+
/**
|
|
8
|
+
* 瓦片矩阵集 TILEMATRIXSET(球面墨卡托 EPSG:3857)
|
|
9
|
+
* @defaultValue 'w'
|
|
10
|
+
*/
|
|
11
|
+
tileMatrixSet?: string;
|
|
12
|
+
/**
|
|
13
|
+
* 样式 STYLE
|
|
14
|
+
* @defaultValue 'default'
|
|
15
|
+
*/
|
|
16
|
+
style?: string;
|
|
17
|
+
/**
|
|
18
|
+
* 瓦片格式 FORMAT
|
|
19
|
+
* @defaultValue 'tiles'
|
|
20
|
+
*/
|
|
21
|
+
format?: string;
|
|
22
|
+
/** 子域名列表,替换 url 中的 {s} 展开为多条 tiles */
|
|
23
|
+
subdomains?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* 瓦片尺寸
|
|
26
|
+
* @defaultValue 256
|
|
27
|
+
*/
|
|
28
|
+
tileSize?: number;
|
|
29
|
+
/** 版权信息 */
|
|
30
|
+
attribution?: string;
|
|
31
|
+
/** 透传查询参数(如 { tk } 等鉴权参数) */
|
|
32
|
+
params?: Record<string, string | undefined>;
|
|
33
|
+
}
|
|
34
|
+
/** 构造 WMTS GetTile(KVP)栅格数据源规格,可直接用于 MaplibreSource。 */
|
|
35
|
+
export declare function wmtsRasterSource(options: WmtsSourceOptions): RasterSourceSpecification;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function buildTileUrl(base, options) {
|
|
2
|
+
const query = /* @__PURE__ */ new Map([
|
|
3
|
+
["SERVICE", "WMTS"],
|
|
4
|
+
["REQUEST", "GetTile"],
|
|
5
|
+
["VERSION", "1.0.0"],
|
|
6
|
+
["LAYER", options.layer],
|
|
7
|
+
["STYLE", options.style ?? "default"],
|
|
8
|
+
["TILEMATRIXSET", options.tileMatrixSet ?? "w"],
|
|
9
|
+
["FORMAT", options.format ?? "tiles"],
|
|
10
|
+
["TILEMATRIX", "{z}"],
|
|
11
|
+
["TILEROW", "{y}"],
|
|
12
|
+
["TILECOL", "{x}"]
|
|
13
|
+
]);
|
|
14
|
+
for (const [key, value] of Object.entries(options.params ?? {})) {
|
|
15
|
+
if (value !== void 0) query.set(key, value);
|
|
16
|
+
}
|
|
17
|
+
const qs = Array.from(query, ([k, v]) => `${k}=${v}`).join("&");
|
|
18
|
+
return `${base}${base.includes("?") ? "&" : "?"}${qs}`;
|
|
19
|
+
}
|
|
20
|
+
export function wmtsRasterSource(options) {
|
|
21
|
+
const { subdomains } = options;
|
|
22
|
+
const tiles = subdomains?.length && options.url.includes("{s}") ? subdomains.map((s) => buildTileUrl(options.url.replace("{s}", s), options)) : [buildTileUrl(options.url, options)];
|
|
23
|
+
return {
|
|
24
|
+
type: "raster",
|
|
25
|
+
tiles,
|
|
26
|
+
tileSize: options.tileSize ?? 256,
|
|
27
|
+
...options.attribution ? { attribution: options.attribution } : {}
|
|
28
|
+
};
|
|
29
|
+
}
|