huweili-cesium 1.2.76 → 1.2.78
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/js/labelDiv.js +6 -1
- package/js/movePoint.js +9 -1
- package/js/tileProviders.js +24 -52
- package/js/toolbar/basemapSwitcher.js +27 -134
- package/js/utils/mapImagery.js +47 -39
- package/package.json +1 -1
package/js/labelDiv.js
CHANGED
|
@@ -143,7 +143,12 @@ export function labelDiv() {
|
|
|
143
143
|
const flyingHandPhone = info?.flyingHandPhone ?? '--';
|
|
144
144
|
const frequencyBand = info?.frequencyBand ?? '--';
|
|
145
145
|
const receiveTime = info?.receiveTime ?? '--';
|
|
146
|
-
const
|
|
146
|
+
const groundLinkLng = info?.groundLinkLng ?? '--';
|
|
147
|
+
const groundLinkLat = info?.groundLinkLat ?? '--';
|
|
148
|
+
const flyingHandPosition =
|
|
149
|
+
groundLinkLng !== '--' && groundLinkLat !== '--'
|
|
150
|
+
? `${groundLinkLng},${groundLinkLat}`
|
|
151
|
+
: (info?.flyingHandPosition ?? '--');
|
|
147
152
|
|
|
148
153
|
// 处理距离(保留1位小数)
|
|
149
154
|
const parseDistance = parseFloat(info?.distance);
|
package/js/movePoint.js
CHANGED
|
@@ -247,6 +247,9 @@ export function movePointConfig(baseUrl) {
|
|
|
247
247
|
modelEntity.scratchFarFutureTime ||= new Cesium.JulianDate()
|
|
248
248
|
|
|
249
249
|
// 如果存在实体,确保实体属性实时同步
|
|
250
|
+
const groundLinkLng = Number(options.GROUND_LINK_LNG)
|
|
251
|
+
const groundLinkLat = Number(options.GROUND_LINK_LAT)
|
|
252
|
+
|
|
250
253
|
const info = modelEntity.info || (modelEntity.info = {})
|
|
251
254
|
info.pointId = pointId
|
|
252
255
|
info.lng = lng
|
|
@@ -255,7 +258,12 @@ export function movePointConfig(baseUrl) {
|
|
|
255
258
|
info.speed = speed
|
|
256
259
|
info.flyingHandName = options.flyingHandName || ''
|
|
257
260
|
info.flyingHandPhone = options.flyingHandPhone || ''
|
|
258
|
-
info.
|
|
261
|
+
info.groundLinkLng = Number.isFinite(groundLinkLng) ? groundLinkLng.toFixed(4) : '--'
|
|
262
|
+
info.groundLinkLat = Number.isFinite(groundLinkLat) ? groundLinkLat.toFixed(4) : '--'
|
|
263
|
+
info.flyingHandPosition =
|
|
264
|
+
info.groundLinkLng !== '--' && info.groundLinkLat !== '--'
|
|
265
|
+
? `${info.groundLinkLng},${info.groundLinkLat}`
|
|
266
|
+
: '--'
|
|
259
267
|
info.frequencyBand = options.frequencyBand || ''
|
|
260
268
|
info.distance = options.distance || ''
|
|
261
269
|
info.receiveTime = options.receiveTime || ''
|
package/js/tileProviders.js
CHANGED
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 自定义地图颜色瓦片函数
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* 提供在Cesium地图上自定义地图颜色瓦片的功能
|
|
5
5
|
* 支持自定义地图颜色风格,如深蓝色、深黑色等各种自定义颜色
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* @author huweili
|
|
8
8
|
* @email czxyhuweili@163.com
|
|
9
9
|
* @version 1.0.0
|
|
10
10
|
*/
|
|
11
11
|
import * as Cesium from 'cesium'
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* 将十六进制颜色字符串转换为RGB对象(使用位运算优化)
|
|
15
|
-
* @param {string|Object} color 十六进制颜色字符串或RGB对象
|
|
16
|
-
* @returns {Object} RGB对象
|
|
17
|
-
*/
|
|
18
13
|
export const hexToRgb = (color) => {
|
|
19
|
-
// 如果已经是RGB对象,直接返回
|
|
20
14
|
if (typeof color === 'object' && color.r !== undefined && color.g !== undefined && color.b !== undefined) {
|
|
21
15
|
return color
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
// 如果是十六进制字符串,转换为RGB对象
|
|
17
|
+
|
|
25
18
|
if (typeof color === 'string') {
|
|
26
|
-
// 移除#号并兼容 3 位十六进制写法
|
|
27
19
|
const normalizedHex = color.trim().replace('#', '')
|
|
28
20
|
const hex = normalizedHex.length === 3
|
|
29
21
|
? normalizedHex.split('').map((ch) => `${ch}${ch}`).join('')
|
|
@@ -32,62 +24,49 @@ export const hexToRgb = (color) => {
|
|
|
32
24
|
if (!/^[0-9a-fA-F]{6}$/.test(hex)) {
|
|
33
25
|
return { r: 0, g: 0, b: 0 }
|
|
34
26
|
}
|
|
35
|
-
|
|
36
|
-
// 使用位运算解析RGB值(更高效)
|
|
27
|
+
|
|
37
28
|
const int = parseInt(hex, 16)
|
|
38
29
|
const r = (int >> 16) & 0xFF
|
|
39
30
|
const g = (int >> 8) & 0xFF
|
|
40
31
|
const b = int & 0xFF
|
|
41
|
-
|
|
32
|
+
|
|
42
33
|
return { r, g, b }
|
|
43
34
|
}
|
|
44
|
-
|
|
45
|
-
// 默认返回黑色
|
|
35
|
+
|
|
46
36
|
return { r: 0, g: 0, b: 0 }
|
|
47
37
|
}
|
|
48
38
|
|
|
49
|
-
/**
|
|
50
|
-
* 处理地图配置中的颜色风格,将十六进制颜色转换为RGB对象
|
|
51
|
-
* @param {Object} mapOptions 地图配置
|
|
52
|
-
* @returns {Object} 处理后的地图配置
|
|
53
|
-
*/
|
|
54
39
|
export const processMapConfigColors = (mapOptions) => {
|
|
55
|
-
if (!mapOptions
|
|
40
|
+
if (!mapOptions) {
|
|
56
41
|
return mapOptions
|
|
57
42
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
if (basemap.customMapColorStyle.MapBaseColor) {
|
|
64
|
-
basemap.customMapColorStyle.MapBaseColor = hexToRgb(basemap.customMapColorStyle.MapBaseColor)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 转换RoadLightColor
|
|
68
|
-
if (basemap.customMapColorStyle.RoadLightColor) {
|
|
69
|
-
basemap.customMapColorStyle.RoadLightColor = hexToRgb(basemap.customMapColorStyle.RoadLightColor)
|
|
70
|
-
}
|
|
43
|
+
|
|
44
|
+
const normalizeStyle = (style) => {
|
|
45
|
+
if (!style) return
|
|
46
|
+
if (style.MapBaseColor) {
|
|
47
|
+
style.MapBaseColor = hexToRgb(style.MapBaseColor)
|
|
71
48
|
}
|
|
49
|
+
if (style.RoadLightColor) {
|
|
50
|
+
style.RoadLightColor = hexToRgb(style.RoadLightColor)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
mapOptions.basemaps?.forEach((basemap) => {
|
|
55
|
+
normalizeStyle(basemap.customMapColorStyle)
|
|
72
56
|
})
|
|
73
|
-
|
|
57
|
+
|
|
58
|
+
normalizeStyle(mapOptions.coexistMap?.customMapColorStyle)
|
|
59
|
+
|
|
74
60
|
return mapOptions
|
|
75
61
|
}
|
|
76
62
|
|
|
77
|
-
/**
|
|
78
|
-
* 自定义地图颜色瓦片提供者
|
|
79
|
-
* 将原始地图瓦片转换为自定义地图颜色风格
|
|
80
|
-
*/
|
|
81
63
|
export class customColorTileProvider extends Cesium.UrlTemplateImageryProvider {
|
|
82
|
-
constructor(
|
|
83
|
-
options,
|
|
84
|
-
custumMapColorStyle
|
|
85
|
-
) {
|
|
64
|
+
constructor(options, custumMapColorStyle) {
|
|
86
65
|
super(options)
|
|
87
66
|
this.customMapColorStyle = custumMapColorStyle || {
|
|
88
67
|
enabled: true,
|
|
89
68
|
MapBaseColor: { r: 9, g: 20, b: 46 },
|
|
90
|
-
RoadLightColor: { r: 125, g: 165, b: 255 }
|
|
69
|
+
RoadLightColor: { r: 125, g: 165, b: 255 },
|
|
91
70
|
}
|
|
92
71
|
}
|
|
93
72
|
|
|
@@ -108,9 +87,6 @@ export class customColorTileProvider extends Cesium.UrlTemplateImageryProvider {
|
|
|
108
87
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
109
88
|
const data = imageData.data
|
|
110
89
|
|
|
111
|
-
// 目标风格:深蓝暗色底图 + 亮蓝道路/文字(接近你第二张图)
|
|
112
|
-
// 说明:将原始亮度做反相,再映射到蓝色梯度
|
|
113
|
-
// 原图中"亮背景"会变成深蓝;"暗线条/文字"会变成亮蓝
|
|
114
90
|
const MapBaseColor = this.customMapColorStyle.MapBaseColor
|
|
115
91
|
const RoadLightColor = this.customMapColorStyle.RoadLightColor
|
|
116
92
|
|
|
@@ -119,14 +95,10 @@ export class customColorTileProvider extends Cesium.UrlTemplateImageryProvider {
|
|
|
119
95
|
const g = data[i + 1]
|
|
120
96
|
const b = data[i + 2]
|
|
121
97
|
|
|
122
|
-
// 感知亮度
|
|
123
98
|
const luma = 0.299 * r + 0.587 * g + 0.114 * b
|
|
124
|
-
|
|
125
|
-
// 反相强度:亮背景->低强度(更暗),暗元素->高强度(更亮)
|
|
126
99
|
const inv = 1 - luma / 255
|
|
127
100
|
const intensity = Math.pow(Math.max(0, Math.min(1, inv)), 1.15)
|
|
128
101
|
|
|
129
|
-
// 映射到蓝色范围
|
|
130
102
|
data[i] = MapBaseColor.r + (RoadLightColor.r - MapBaseColor.r) * intensity
|
|
131
103
|
data[i + 1] = MapBaseColor.g + (RoadLightColor.g - MapBaseColor.g) * intensity
|
|
132
104
|
data[i + 2] = MapBaseColor.b + (RoadLightColor.b - MapBaseColor.b) * intensity
|
|
@@ -1,159 +1,79 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 提供在 Cesium 地图上切换底图的功能
|
|
5
|
-
* 支持在原始底图和高德卫星影像之间切换
|
|
6
|
-
*
|
|
7
|
-
* @author huweili
|
|
8
|
-
* @email czxyhuweili@163.com
|
|
9
|
-
* @version 1.0.0
|
|
2
|
+
* 底图切换器(本地调试副本,源自 huweili-cesium)
|
|
10
3
|
*/
|
|
11
|
-
import
|
|
12
|
-
import { customColorTileProvider } from '../tileProviders'
|
|
4
|
+
import { applyImageryLayers } from './mapImagery.js'
|
|
13
5
|
|
|
14
|
-
/**
|
|
15
|
-
* 底图 ID 枚举(从配置动态生成)
|
|
16
|
-
*/
|
|
17
6
|
export const BasemapIds = window.MapConfig?.basemaps?.reduce((acc, item) => {
|
|
18
7
|
const key = item.id.toUpperCase().replace(/-/g, '_')
|
|
19
8
|
acc[key] = item.id
|
|
20
9
|
return acc
|
|
21
10
|
}, {}) || {}
|
|
22
11
|
|
|
23
|
-
/**
|
|
24
|
-
* 创建底图切换器
|
|
25
|
-
* @returns {Object} 底图切换器对象
|
|
26
|
-
*/
|
|
27
12
|
export function createBasemapSwitcher() {
|
|
28
|
-
// 标记当前底图 id
|
|
29
13
|
let currentBasemapId = null
|
|
30
14
|
|
|
31
|
-
/**
|
|
32
|
-
* 获取所有底图配置
|
|
33
|
-
* @returns {Array} 底图配置数组
|
|
34
|
-
*/
|
|
35
15
|
const getBasemaps = () => window.MapConfig?.basemaps || []
|
|
16
|
+
const getBasemapById = (id) => getBasemaps().find((b) => b.id === id)
|
|
36
17
|
|
|
37
|
-
/**
|
|
38
|
-
* 根据 id 查找底图配置
|
|
39
|
-
* @param {string} id 底图 id
|
|
40
|
-
* @returns {Object | null} 底图配置对象
|
|
41
|
-
*/
|
|
42
|
-
const getBasemapById = (id) => getBasemaps().find(b => b.id === id)
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 加载底图
|
|
46
|
-
* @param viewer Cesium Viewer 实例
|
|
47
|
-
* @param {Object} basemapConfig 底图配置对象
|
|
48
|
-
*/
|
|
49
18
|
const loadBasemap = (viewer, basemapConfig) => {
|
|
50
19
|
if (!viewer || !basemapConfig) return
|
|
51
|
-
|
|
52
|
-
// 清除现有底图
|
|
53
|
-
viewer.imageryLayers.removeAll()
|
|
54
|
-
|
|
55
|
-
// 创建新底图
|
|
56
|
-
let layer
|
|
57
|
-
const tileProviderOptions = {
|
|
58
|
-
url: basemapConfig.url,
|
|
59
|
-
subdomains: ['1', '2', '3', '4'],
|
|
60
|
-
maximumLevel: 18,
|
|
61
|
-
credit: basemapConfig.name
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const provider = basemapConfig.customMapColorStyle?.enabled
|
|
65
|
-
? new customColorTileProvider(tileProviderOptions, basemapConfig.customMapColorStyle)
|
|
66
|
-
: new Cesium.UrlTemplateImageryProvider(tileProviderOptions)
|
|
67
|
-
|
|
68
|
-
layer = new Cesium.ImageryLayer(provider)
|
|
69
|
-
|
|
70
|
-
// 添加底图
|
|
71
|
-
viewer.imageryLayers.add(layer)
|
|
20
|
+
applyImageryLayers(viewer, window.MapConfig || {}, basemapConfig)
|
|
72
21
|
currentBasemapId = basemapConfig.id
|
|
22
|
+
window._currentBasemapId = basemapConfig.id
|
|
73
23
|
}
|
|
74
24
|
|
|
75
|
-
/**
|
|
76
|
-
* 通过 id 切换底图
|
|
77
|
-
* @param viewer Cesium Viewer 实例
|
|
78
|
-
* @param {string} id 底图 id
|
|
79
|
-
*/
|
|
80
25
|
const switchById = (viewer, id) => {
|
|
81
26
|
const basemap = getBasemapById(id)
|
|
82
27
|
if (!basemap) {
|
|
83
|
-
console.
|
|
28
|
+
console.warn(`Basemap not found with id: ${id}`)
|
|
84
29
|
return
|
|
85
30
|
}
|
|
86
31
|
loadBasemap(viewer, basemap)
|
|
87
32
|
}
|
|
88
33
|
|
|
89
|
-
/**
|
|
90
|
-
* 切换到高德卫星影像
|
|
91
|
-
* @param viewer Cesium Viewer 实例
|
|
92
|
-
*/
|
|
93
34
|
const toggleSatelliteBasemap = (viewer) => {
|
|
94
35
|
if (!viewer || !window.MapConfig) return
|
|
95
36
|
|
|
96
37
|
if (currentBasemapId === BasemapIds.AMAP_SATELLITE) {
|
|
97
|
-
|
|
98
|
-
const defaultBasemap = getBasemaps().find(b => b.show)
|
|
38
|
+
const defaultBasemap = getBasemaps().find((b) => b.show)
|
|
99
39
|
if (defaultBasemap) {
|
|
100
40
|
loadBasemap(viewer, defaultBasemap)
|
|
101
41
|
}
|
|
102
42
|
} else {
|
|
103
|
-
// 切换到卫星影像
|
|
104
43
|
switchById(viewer, BasemapIds.AMAP_SATELLITE)
|
|
105
44
|
}
|
|
106
45
|
}
|
|
107
46
|
|
|
108
|
-
|
|
109
|
-
* 获取当前底图 id
|
|
110
|
-
* @returns {string | null} 当前底图 id
|
|
111
|
-
*/
|
|
112
|
-
const getCurrentBasemapId = () => currentBasemapId
|
|
47
|
+
const getCurrentBasemapId = () => currentBasemapId ?? window._currentBasemapId ?? null
|
|
113
48
|
|
|
114
|
-
/**
|
|
115
|
-
* 初始化,设置当前底图 id
|
|
116
|
-
* @param {string} id 底图 id
|
|
117
|
-
*/
|
|
118
49
|
const setCurrentBasemapId = (id) => {
|
|
119
50
|
currentBasemapId = id
|
|
120
51
|
}
|
|
121
52
|
|
|
122
|
-
/**
|
|
123
|
-
* 在地图容器右侧打开 / 关闭底图选择浮层
|
|
124
|
-
* @param {import('cesium').Viewer} viewer
|
|
125
|
-
* @param {HTMLButtonElement | null} triggerButton 工具栏触发按钮,用于点击外部关闭时排除
|
|
126
|
-
*/
|
|
127
53
|
const toggleBasemapPickerPanel = (viewer, triggerButton) => {
|
|
128
54
|
if (!viewer?.container) return
|
|
129
55
|
|
|
130
|
-
const container = viewer.container
|
|
131
56
|
const PANEL_ID = 'cesium-basemap-picker-panel'
|
|
132
|
-
|
|
133
57
|
let panel = document.getElementById(PANEL_ID)
|
|
134
58
|
|
|
135
59
|
const syncPanelViewport = () => {
|
|
136
60
|
if (!panel || panel.style.display === 'none') return
|
|
137
61
|
const buttonRect = triggerButton?.getBoundingClientRect()
|
|
138
62
|
if (!buttonRect) return
|
|
139
|
-
|
|
63
|
+
|
|
140
64
|
const margin = 35
|
|
141
65
|
const panelRect = panel.getBoundingClientRect()
|
|
142
|
-
|
|
143
|
-
// 获取 Cesium 工具栏的位置信息
|
|
144
66
|
const toolbar = document.querySelector('.cesium-viewer-toolbar')
|
|
145
67
|
const toolbarRect = toolbar?.getBoundingClientRect()
|
|
146
|
-
|
|
147
|
-
// 计算left
|
|
68
|
+
|
|
148
69
|
let left = (toolbarRect?.left || 0) + (toolbarRect?.width || 0)
|
|
149
|
-
// 计算top:确保面板底部与按钮底部对齐
|
|
150
70
|
let top = buttonRect.bottom - panelRect.height
|
|
151
|
-
|
|
71
|
+
|
|
152
72
|
if (top < 0) top = margin
|
|
153
73
|
if (top + panelRect.height > window.innerHeight) {
|
|
154
74
|
top = window.innerHeight - panelRect.height - margin
|
|
155
75
|
}
|
|
156
|
-
|
|
76
|
+
|
|
157
77
|
panel.style.position = 'fixed'
|
|
158
78
|
panel.style.right = 'auto'
|
|
159
79
|
panel.style.bottom = 'auto'
|
|
@@ -203,37 +123,21 @@ export function createBasemapSwitcher() {
|
|
|
203
123
|
display: none;
|
|
204
124
|
flex-direction: column;
|
|
205
125
|
padding: 8px;
|
|
206
|
-
` + `
|
|
207
|
-
/* 自定义滚动条样式 - WebKit内核浏览器 */
|
|
208
126
|
scrollbar-width: thin;
|
|
209
127
|
scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
|
|
210
128
|
`
|
|
211
129
|
const list = document.createElement('div')
|
|
212
130
|
list.setAttribute('data-role', 'basemap-list')
|
|
213
|
-
list.style.cssText =
|
|
214
|
-
display: grid;
|
|
215
|
-
grid-template-columns: repeat(2, 1fr);
|
|
216
|
-
gap: 8px;
|
|
217
|
-
`
|
|
131
|
+
list.style.cssText = 'display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px;'
|
|
218
132
|
panel.appendChild(list)
|
|
219
133
|
document.body.appendChild(panel)
|
|
220
|
-
|
|
221
|
-
// 添加滚动条样式(WebKit内核浏览器)
|
|
134
|
+
|
|
222
135
|
const style = document.createElement('style')
|
|
223
136
|
style.textContent = `
|
|
224
|
-
#${PANEL_ID}::-webkit-scrollbar {
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
#${PANEL_ID}::-webkit-scrollbar-
|
|
228
|
-
background: transparent;
|
|
229
|
-
}
|
|
230
|
-
#${PANEL_ID}::-webkit-scrollbar-thumb {
|
|
231
|
-
background: rgba(255, 255, 255, 0.2);
|
|
232
|
-
border-radius: 3px;
|
|
233
|
-
}
|
|
234
|
-
#${PANEL_ID}::-webkit-scrollbar-thumb:hover {
|
|
235
|
-
background: rgba(255, 255, 255, 0.35);
|
|
236
|
-
}
|
|
137
|
+
#${PANEL_ID}::-webkit-scrollbar { width: 6px; }
|
|
138
|
+
#${PANEL_ID}::-webkit-scrollbar-track { background: transparent; }
|
|
139
|
+
#${PANEL_ID}::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 3px; }
|
|
140
|
+
#${PANEL_ID}::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.35); }
|
|
237
141
|
`
|
|
238
142
|
document.head.appendChild(style)
|
|
239
143
|
}
|
|
@@ -258,8 +162,7 @@ export function createBasemapSwitcher() {
|
|
|
258
162
|
align-items: center;
|
|
259
163
|
justify-content: center;
|
|
260
164
|
`
|
|
261
|
-
|
|
262
|
-
// 缩略图容器
|
|
165
|
+
|
|
263
166
|
const imgContainer = document.createElement('div')
|
|
264
167
|
imgContainer.style.cssText = `
|
|
265
168
|
width: 100%;
|
|
@@ -269,13 +172,10 @@ export function createBasemapSwitcher() {
|
|
|
269
172
|
border: 2px solid ${active ? '#3B82F6' : 'transparent'};
|
|
270
173
|
position: relative;
|
|
271
174
|
`
|
|
272
|
-
|
|
273
|
-
// 应用自定义背景色
|
|
274
175
|
if (bm.customMapColorStyle?.enabled) {
|
|
275
176
|
imgContainer.style.backgroundColor = bm.customMapColorStyle.MapBaseColor
|
|
276
177
|
}
|
|
277
|
-
|
|
278
|
-
// 缩略图
|
|
178
|
+
|
|
279
179
|
const img = document.createElement('img')
|
|
280
180
|
img.src = import.meta.env.BASE_URL + bm.thumbnail || ''
|
|
281
181
|
img.style.cssText = `
|
|
@@ -284,13 +184,11 @@ export function createBasemapSwitcher() {
|
|
|
284
184
|
object-fit: cover;
|
|
285
185
|
opacity: ${bm.customMapColorStyle?.enabled ? 0.7 : 1};
|
|
286
186
|
`
|
|
287
|
-
img.onerror = function() {
|
|
187
|
+
img.onerror = function () {
|
|
288
188
|
this.style.display = 'none'
|
|
289
189
|
}
|
|
290
|
-
|
|
291
190
|
imgContainer.appendChild(img)
|
|
292
|
-
|
|
293
|
-
// 名称
|
|
191
|
+
|
|
294
192
|
const nameSpan = document.createElement('span')
|
|
295
193
|
nameSpan.textContent = bm.name
|
|
296
194
|
nameSpan.style.cssText = `
|
|
@@ -299,10 +197,9 @@ export function createBasemapSwitcher() {
|
|
|
299
197
|
font-weight: ${active ? '600' : '400'};
|
|
300
198
|
text-align: center;
|
|
301
199
|
`
|
|
302
|
-
|
|
200
|
+
|
|
303
201
|
row.appendChild(imgContainer)
|
|
304
202
|
row.appendChild(nameSpan)
|
|
305
|
-
|
|
306
203
|
row.onmouseenter = () => {
|
|
307
204
|
row.style.background = 'rgba(255, 255, 255, 0.08)'
|
|
308
205
|
}
|
|
@@ -312,19 +209,14 @@ export function createBasemapSwitcher() {
|
|
|
312
209
|
row.onclick = (e) => {
|
|
313
210
|
e.stopPropagation()
|
|
314
211
|
switchById(viewer, bm.id)
|
|
315
|
-
window._currentBasemapId = bm.id
|
|
316
212
|
hidePanel()
|
|
317
213
|
}
|
|
318
214
|
listEl.appendChild(row)
|
|
319
215
|
})
|
|
320
216
|
|
|
321
217
|
panel.style.display = 'flex'
|
|
322
|
-
|
|
323
|
-
// 等待面板渲染完成后再定位
|
|
324
218
|
requestAnimationFrame(() => {
|
|
325
|
-
requestAnimationFrame(() =>
|
|
326
|
-
syncPanelViewport()
|
|
327
|
-
})
|
|
219
|
+
requestAnimationFrame(() => syncPanelViewport())
|
|
328
220
|
})
|
|
329
221
|
|
|
330
222
|
detachOutside()
|
|
@@ -345,7 +237,8 @@ export function createBasemapSwitcher() {
|
|
|
345
237
|
document.addEventListener('pointerdown', onOutsidePointer, true)
|
|
346
238
|
})
|
|
347
239
|
})
|
|
348
|
-
panel._removeOutsideListener = () =>
|
|
240
|
+
panel._removeOutsideListener = () =>
|
|
241
|
+
document.removeEventListener('pointerdown', onOutsidePointer, true)
|
|
349
242
|
}
|
|
350
243
|
|
|
351
244
|
return {
|
|
@@ -355,6 +248,6 @@ export function createBasemapSwitcher() {
|
|
|
355
248
|
getBasemapById,
|
|
356
249
|
getCurrentBasemapId,
|
|
357
250
|
setCurrentBasemapId,
|
|
358
|
-
toggleBasemapPickerPanel
|
|
251
|
+
toggleBasemapPickerPanel,
|
|
359
252
|
}
|
|
360
253
|
}
|
package/js/utils/mapImagery.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 底图与离线共存图层加载(本地调试副本,源自 huweili-cesium)
|
|
3
3
|
*/
|
|
4
4
|
import * as Cesium from 'cesium'
|
|
5
5
|
import { customColorTileProvider, hexToRgb } from '../tileProviders.js'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
* 解析 coexistMap 自定义配色(支持 hex 或已转换的 rgb)
|
|
9
|
-
* @param {Object} coexistMap
|
|
10
|
-
* @returns {Object | null}
|
|
11
|
-
*/
|
|
12
|
-
function resolveCoexistColorStyle(coexistMap) {
|
|
13
|
-
const style = coexistMap?.customMapColorStyle
|
|
7
|
+
function resolveColorStyle(style) {
|
|
14
8
|
if (!style?.enabled) return null
|
|
15
9
|
|
|
16
10
|
return {
|
|
@@ -26,10 +20,35 @@ function resolveCoexistColorStyle(coexistMap) {
|
|
|
26
20
|
}
|
|
27
21
|
}
|
|
28
22
|
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
/** 离线瓦片配色:跟随当前在线底图(方案 A) */
|
|
24
|
+
function resolveOfflineColorStyle(basemapConfig) {
|
|
25
|
+
return resolveColorStyle(basemapConfig?.customMapColorStyle)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function syncCoexistOfflineColorStyle(mapOptions, basemapConfig) {
|
|
29
|
+
const coexist = mapOptions?.coexistMap
|
|
30
|
+
if (!coexist?.enabled) return
|
|
31
|
+
|
|
32
|
+
const style = basemapConfig?.customMapColorStyle
|
|
33
|
+
if (style?.enabled) {
|
|
34
|
+
coexist.customMapColorStyle = {
|
|
35
|
+
enabled: true,
|
|
36
|
+
MapBaseColor: style.MapBaseColor,
|
|
37
|
+
RoadLightColor: style.RoadLightColor,
|
|
38
|
+
}
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
coexist.customMapColorStyle = { enabled: false }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 当前在线底图是否应叠加离线共存层(basemap.hideOfflineCoexist === true 时不叠加) */
|
|
46
|
+
function shouldShowOfflineCoexistLayer(coexist, basemapConfig) {
|
|
47
|
+
if (!coexist?.enabled || !coexist.map?.url) return false
|
|
48
|
+
if (basemapConfig?.hideOfflineCoexist) return false
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
export function createBasemapProvider(basemapConfig) {
|
|
34
53
|
const tileProviderOptions = {
|
|
35
54
|
url: basemapConfig.url,
|
|
@@ -38,19 +57,15 @@ export function createBasemapProvider(basemapConfig) {
|
|
|
38
57
|
credit: basemapConfig.name,
|
|
39
58
|
}
|
|
40
59
|
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
const colorStyle = resolveColorStyle(basemapConfig?.customMapColorStyle)
|
|
61
|
+
if (colorStyle) {
|
|
62
|
+
return new customColorTileProvider(tileProviderOptions, colorStyle)
|
|
43
63
|
}
|
|
44
64
|
|
|
45
65
|
return new Cesium.UrlTemplateImageryProvider(tileProviderOptions)
|
|
46
66
|
}
|
|
47
67
|
|
|
48
|
-
|
|
49
|
-
* 离线瓦片(限定矩形范围,仅在该区域内请求瓦片)
|
|
50
|
-
* @param {Object} coexistMap mapConfig.coexistMap
|
|
51
|
-
* @returns {Cesium.ImageryProvider | null}
|
|
52
|
-
*/
|
|
53
|
-
export function createCoexistOfflineProvider(coexistMap) {
|
|
68
|
+
export function createCoexistOfflineProvider(coexistMap, basemapConfig) {
|
|
54
69
|
const offline = coexistMap?.map
|
|
55
70
|
if (!offline?.url) return null
|
|
56
71
|
|
|
@@ -71,7 +86,7 @@ export function createCoexistOfflineProvider(coexistMap) {
|
|
|
71
86
|
)
|
|
72
87
|
}
|
|
73
88
|
|
|
74
|
-
const colorStyle =
|
|
89
|
+
const colorStyle = resolveOfflineColorStyle(basemapConfig)
|
|
75
90
|
if (colorStyle) {
|
|
76
91
|
return new customColorTileProvider(options, colorStyle)
|
|
77
92
|
}
|
|
@@ -79,11 +94,6 @@ export function createCoexistOfflineProvider(coexistMap) {
|
|
|
79
94
|
return new Cesium.UrlTemplateImageryProvider(options)
|
|
80
95
|
}
|
|
81
96
|
|
|
82
|
-
/**
|
|
83
|
-
* 解析在线底图:coexist 开启且配置了 mapId 时优先用该底图,否则用 show:true 的底图
|
|
84
|
-
* @param {Object} mapOptions
|
|
85
|
-
* @returns {Object | undefined}
|
|
86
|
-
*/
|
|
87
97
|
export function resolveOnlineBasemap(mapOptions) {
|
|
88
98
|
const basemaps = mapOptions?.basemaps || []
|
|
89
99
|
const coexist = mapOptions?.coexistMap
|
|
@@ -96,14 +106,9 @@ export function resolveOnlineBasemap(mapOptions) {
|
|
|
96
106
|
return basemaps.find((b) => b.show === true)
|
|
97
107
|
}
|
|
98
108
|
|
|
99
|
-
/**
|
|
100
|
-
* 在线底图(底层,全球)+ 离线底图(顶层,仅 bounds 内加载)
|
|
101
|
-
* @param {import('cesium').Viewer} viewer
|
|
102
|
-
* @param {Object} mapOptions
|
|
103
|
-
* @param {Object} basemapConfig
|
|
104
|
-
* @returns {{ onlineLayer: Cesium.ImageryLayer, offlineLayer: Cesium.ImageryLayer | null }}
|
|
105
|
-
*/
|
|
106
109
|
export function applyImageryLayers(viewer, mapOptions, basemapConfig) {
|
|
110
|
+
syncCoexistOfflineColorStyle(mapOptions, basemapConfig)
|
|
111
|
+
|
|
107
112
|
viewer.imageryLayers.removeAll()
|
|
108
113
|
|
|
109
114
|
const onlineLayer = new Cesium.ImageryLayer(createBasemapProvider(basemapConfig))
|
|
@@ -111,23 +116,26 @@ export function applyImageryLayers(viewer, mapOptions, basemapConfig) {
|
|
|
111
116
|
|
|
112
117
|
let offlineLayer = null
|
|
113
118
|
const coexist = mapOptions?.coexistMap
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
|
|
120
|
+
if (shouldShowOfflineCoexistLayer(coexist, basemapConfig)) {
|
|
121
|
+
const offlineProvider = createCoexistOfflineProvider(coexist, basemapConfig)
|
|
116
122
|
if (offlineProvider) {
|
|
117
123
|
offlineLayer = new Cesium.ImageryLayer(offlineProvider)
|
|
118
124
|
viewer.imageryLayers.add(offlineLayer)
|
|
125
|
+
const colorNote = basemapConfig.customMapColorStyle?.enabled
|
|
126
|
+
? ',离线配色跟随在线底图'
|
|
127
|
+
: ',离线无配色滤镜'
|
|
119
128
|
console.log(
|
|
120
|
-
`离线共存已启用:${coexist.map?.name},范围外使用在线底图「${basemapConfig.name}
|
|
129
|
+
`离线共存已启用:${coexist.map?.name},范围外使用在线底图「${basemapConfig.name}」${colorNote}`,
|
|
121
130
|
)
|
|
122
131
|
}
|
|
132
|
+
} else if (coexist?.enabled && basemapConfig?.hideOfflineCoexist) {
|
|
133
|
+
console.log(`离线共存已跳过:当前底图「${basemapConfig.name}」配置了 hideOfflineCoexist`)
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
return { onlineLayer, offlineLayer }
|
|
126
137
|
}
|
|
127
138
|
|
|
128
|
-
/**
|
|
129
|
-
* 底图切换后重新叠加离线层(仅替换在线层,保留离线层逻辑:先清再全量加载)
|
|
130
|
-
*/
|
|
131
139
|
export function switchBasemapWithCoexist(viewer, mapOptions, basemapConfig) {
|
|
132
140
|
const layers = applyImageryLayers(viewer, mapOptions, basemapConfig)
|
|
133
141
|
window._currentBasemapId = basemapConfig.id
|