| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /**
- * 底图计划(票 29):把配置里的 `map.basemap` 翻译成「用哪一类 Cesium 影像源、什么 URL」。
- *
- * 纯函数、**不 import cesium** —— 引擎侧(services/cesiumEngine.js)照着这份计划建 provider,
- * 逻辑断言脚本因此能脱浏览器把每种来源(含天地图模板拼装、缺 tk 的失败态)都测到。
- *
- * 为什么单独一层:票 27 故意 `baseLayer: false`(底图未配置就不伪造地理配准),
- * 票 21 负责地形 / 3D Tiles / 倾斜摄影与地面-管线视图切换;底图影像这一层独立成票。
- */
- /** 底图来源(配置里 `map.basemap.source` 的取值)。 */
- export const BASEMAP_SOURCE = {
- NONE: 'none',
- NATURAL_EARTH: 'natural-earth',
- ARCGIS_IMAGERY: 'arcgis-imagery',
- XYZ: 'xyz',
- TIANDITU: 'tianditu',
- }
- /** 底图状态(写进宿主 `data-map-basemap`,也是 getLifecycleStats().basemap 的取值)。 */
- export const BASEMAP_STATE = {
- NOT_CONFIGURED: 'not-configured',
- NATURAL_EARTH: 'natural-earth',
- ARCGIS_IMAGERY: 'arcgis-imagery',
- XYZ: 'xyz',
- TIANDITU: 'tianditu',
- INVALID: 'invalid',
- }
- /**
- * ArcGIS 官方世界影像:免费、免 key(署名即可),模板顺序是 `{z}/{y}/{x}`。
- * 注意本机实测**连不上**(外网被挡),离线环境请用 `natural-earth`。
- */
- export const ARCGIS_WORLD_IMAGERY_URL =
- 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'
- /** Cesium 自带的离线影像(随 `Build/Cesium/Assets` 一起进产物,不需要账号或外网)。 */
- export const NATURAL_EARTH_TMS = 'Assets/Textures/NaturalEarthII'
- /** 天地图子域(生产直连时用;开发走仓库里已有的 `/tianditu.map` 代理,单主机不加子域)。 */
- export const TIANDITU_SUBDOMAINS = ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7']
- export const TIANDITU_LAYERS = {
- img: '影像底图',
- vec: '矢量底图',
- ter: '地形晕渲',
- }
- /**
- * 天地图 WMTS 瓦片模板(tk 拼在查询串里;Cesium 负责替换 `{s}`/`{z}`/`{x}`/`{y}`)。
- * @param {string} base 形如 `/tianditu.map`(开发代理)或 `https://t{s}.tianditu.gov.cn`(生产)
- * @param {string} token 天地图 tk
- * @param {string} layer `img` / `vec` / `ter`
- */
- export function tiandituTileUrl(base, token, layer = 'img') {
- const root = String(base || '').replace(/\/+$/, '')
- return `${root}/${layer}_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${layer}&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${token}`
- }
- function basePlan(state, source, label, extra = {}) {
- return { state, source, label, ready: false, kind: '', url: '', subdomains: [], minimumLevel: null, maximumLevel: null, credit: '', issue: '', ...extra }
- }
- /**
- * 配置 → 底图计划。
- * @param {object} mapConfig 归一化后的 `config.map`
- * @param {object} [options]
- * @param {boolean} [options.dev] 开发态:天地图走仓库自带的 `/tianditu.map` 代理
- * @returns {{state: string, source: string, label: string, ready: boolean, kind: string, url: string,
- * subdomains: string[], minimumLevel: number|null, maximumLevel: number|null, credit: string, issue: string}}
- */
- export function planBasemap(mapConfig = {}, options = {}) {
- const map = mapConfig || {}
- const basemap = map.basemap || {}
- const source = basemap.source || BASEMAP_SOURCE.NONE
- if (source === BASEMAP_SOURCE.NONE) {
- return basePlan(BASEMAP_STATE.NOT_CONFIGURED, source, '底图未配置')
- }
- if (source === BASEMAP_SOURCE.NATURAL_EARTH) {
- return basePlan(BASEMAP_STATE.NATURAL_EARTH, source, '内置离线影像 Natural Earth II', {
- ready: true,
- kind: 'tms',
- url: NATURAL_EARTH_TMS,
- })
- }
- if (source === BASEMAP_SOURCE.ARCGIS_IMAGERY) {
- return basePlan(BASEMAP_STATE.ARCGIS_IMAGERY, source, 'ArcGIS 全球影像(免费免 key)', {
- ready: true,
- kind: 'xyz',
- url: ARCGIS_WORLD_IMAGERY_URL,
- credit: 'Esri, Maxar, Earthstar Geographics',
- })
- }
- if (source === BASEMAP_SOURCE.XYZ) {
- if (!basemap.url) {
- return basePlan(BASEMAP_STATE.INVALID, source, '底图配置无效', { issue: 'xyz 底图缺少 url 模板' })
- }
- return basePlan(BASEMAP_STATE.XYZ, source, '自定义瓦片(XYZ)', {
- ready: true,
- kind: 'xyz',
- url: basemap.url,
- subdomains: basemap.subdomains || [],
- minimumLevel: basemap.minimumLevel,
- maximumLevel: basemap.maximumLevel,
- credit: basemap.credit || '',
- })
- }
- if (source === BASEMAP_SOURCE.TIANDITU) {
- const token = basemap.token || (map.tianditu && map.tianditu.token) || ''
- if (!token) {
- return basePlan(BASEMAP_STATE.INVALID, source, '底图配置无效', {
- issue: '天地图底图缺少 tk(填 map.tianditu.token)',
- })
- }
- const requested = (map.tianditu && map.tianditu.layer) || basemap.layer || 'img'
- const layer = TIANDITU_LAYERS[requested] ? requested : 'img'
- const dev = options.dev === true
- return basePlan(BASEMAP_STATE.TIANDITU, source, `天地图${TIANDITU_LAYERS[layer]}`, {
- ready: true,
- kind: 'xyz',
- url: tiandituTileUrl(dev ? '/tianditu.map' : 'https://t{s}.tianditu.gov.cn', token, layer),
- subdomains: dev ? [] : TIANDITU_SUBDOMAINS,
- credit: '天地图',
- })
- }
- return basePlan(BASEMAP_STATE.INVALID, source, '底图配置无效', { issue: `未知的底图来源 ${source}` })
- }
- /** 引擎状态浮标上的底图措辞(未配置时保持票 27 的原话)。 */
- export function basemapStatusText(plan) {
- const current = plan || planBasemap({})
- if (current.ready) return `底图:${current.label}`
- if (current.state === BASEMAP_STATE.INVALID) return `底图配置无效(${current.issue})· 回退临时影像`
- return '底图未配置(正式底图见票 21)'
- }
|