huweili-cesium 1.2.97 → 1.2.99

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.
Files changed (2) hide show
  1. package/js/glbInfoBadge.js +47 -28
  2. package/package.json +1 -1
@@ -7,9 +7,12 @@
7
7
  import * as Cesium from 'cesium'
8
8
  import { getDroneLabelBatchManager } from './cardPool'
9
9
 
10
- const STYLE_ID = 'glb-info-badge-style'
10
+ const STYLE_ID = 'glb-info-badge-style-v2'
11
11
  const DEFAULT_LABEL_OFFSET = 1
12
- const DEFAULT_PIXEL_GAP = 2
12
+ const DEFAULT_PIXEL_GAP = 0
13
+ const DEFAULT_HEIGHT_SCALE = 0.72
14
+ /** 包围球半径折算到车顶的系数(中心点已在模型中部,无需再加整颗半径) */
15
+ const BOUNDING_SPHERE_TOP_FACTOR = 0.22
13
16
 
14
17
  const scratchBoundingSphere = new Cesium.BoundingSphere()
15
18
  const scratchEnu = new Cesium.Matrix4()
@@ -35,16 +38,16 @@ const ensureGlbInfoBadgeStyle = () => {
35
38
  position: relative;
36
39
  display: inline-flex;
37
40
  align-items: center;
38
- gap: 6px;
39
- padding: 4px 12px 4px 10px;
41
+ gap: 4px;
42
+ padding: 2px 8px 2px 6px;
40
43
  border-radius: 999px;
41
44
  background: linear-gradient(135deg, rgba(8, 20, 40, 0.92) 0%, rgba(12, 32, 58, 0.88) 100%);
42
45
  border: 1px solid rgba(0, 229, 255, 0.45);
43
46
  box-shadow:
44
- inset 0 0 12px rgba(0, 229, 255, 0.08),
45
- 0 0 16px rgba(0, 229, 255, 0.15);
47
+ inset 0 0 8px rgba(0, 229, 255, 0.08),
48
+ 0 0 10px rgba(0, 229, 255, 0.15);
46
49
  overflow: hidden;
47
- backdrop-filter: blur(6px);
50
+ backdrop-filter: blur(4px);
48
51
  white-space: nowrap;
49
52
  }
50
53
  .glb-info-badge-scan {
@@ -58,27 +61,28 @@ const ensureGlbInfoBadgeStyle = () => {
58
61
  pointer-events: none;
59
62
  }
60
63
  .glb-info-badge-dot {
61
- width: 8px;
62
- height: 8px;
64
+ width: 5px;
65
+ height: 5px;
63
66
  border-radius: 50%;
64
67
  flex-shrink: 0;
65
- box-shadow: 0 0 8px currentColor;
68
+ box-shadow: 0 0 5px currentColor;
66
69
  }
67
70
  .glb-info-badge-text {
68
- font-size: 12px;
71
+ font-size: 10px;
69
72
  font-weight: 600;
70
- letter-spacing: 0.08em;
73
+ line-height: 1;
74
+ letter-spacing: 0.06em;
71
75
  color: #e8f7ff;
72
- text-shadow: 0 0 6px rgba(0, 229, 255, 0.5);
76
+ text-shadow: 0 0 4px rgba(0, 229, 255, 0.5);
73
77
  }
74
78
  .glb-info-badge-pointer {
75
79
  width: 0;
76
80
  height: 0;
77
- margin: 2px auto 0;
78
- border-left: 5px solid transparent;
79
- border-right: 5px solid transparent;
80
- border-top: 6px solid rgba(0, 229, 255, 0.55);
81
- filter: drop-shadow(0 0 4px rgba(0, 229, 255, 0.4));
81
+ margin: 1px auto 0;
82
+ border-left: 4px solid transparent;
83
+ border-right: 4px solid transparent;
84
+ border-top: 5px solid rgba(0, 229, 255, 0.55);
85
+ filter: drop-shadow(0 0 3px rgba(0, 229, 255, 0.4));
82
86
  }
83
87
  .glb-info-badge.is-online .glb-info-badge-inner {
84
88
  border-color: rgba(0, 255, 170, 0.55);
@@ -174,8 +178,11 @@ const resolveModelTopWorldPosition = (map, entity, basePos, fallbackOffset) => {
174
178
  if (entity && dataSourceDisplay?.getBoundingSphere) {
175
179
  const ok = dataSourceDisplay.getBoundingSphere(entity, true, scratchBoundingSphere)
176
180
  if (ok && scratchBoundingSphere.radius > 0) {
177
- Cesium.Cartesian3.multiplyByScalar(scratchUp, scratchBoundingSphere.radius, scratchOffset)
178
- return Cesium.Cartesian3.add(scratchBoundingSphere.center, scratchOffset, scratchTop)
181
+ Cesium.Cartesian3.subtract(scratchBoundingSphere.center, basePos, scratchOffset)
182
+ const centerAlongUp = Math.max(0, Cesium.Cartesian3.dot(scratchOffset, scratchUp))
183
+ const topAlongUp = centerAlongUp + scratchBoundingSphere.radius * BOUNDING_SPHERE_TOP_FACTOR
184
+ Cesium.Cartesian3.multiplyByScalar(scratchUp, topAlongUp, scratchOffset)
185
+ return Cesium.Cartesian3.add(basePos, scratchOffset, scratchTop)
179
186
  }
180
187
  }
181
188
 
@@ -190,28 +197,37 @@ const resolveModelTopWorldPosition = (map, entity, basePos, fallbackOffset) => {
190
197
  * @param {Cesium.Cartesian3} topWorldPos
191
198
  * @param {number} minPixelSize
192
199
  * @param {number} pixelGap
200
+ * @param {number} heightScale
193
201
  * @returns {{ x: number, y: number }|null}
194
202
  */
195
- const resolveBadgeScreenPosition = (scene, basePos, topWorldPos, minPixelSize, pixelGap) => {
203
+ const resolveBadgeScreenPosition = (scene, basePos, topWorldPos, minPixelSize, pixelGap, heightScale) => {
196
204
  const anchorWin = scene.cartesianToCanvasCoordinates(basePos)
197
205
  if (!anchorWin || Number.isNaN(anchorWin.x) || Number.isNaN(anchorWin.y)) {
198
206
  return null
199
207
  }
200
208
 
201
- const topWin = scene.cartesianToCanvasCoordinates(topWorldPos)
209
+ const topWin = topWorldPos ? scene.cartesianToCanvasCoordinates(topWorldPos) : null
202
210
  let offsetY = 0
203
211
 
204
212
  if (topWin && !Number.isNaN(topWin.y)) {
205
- offsetY = anchorWin.y - topWin.y
213
+ offsetY = (anchorWin.y - topWin.y) * heightScale
214
+ }
215
+
216
+ // 包围球常大于实际 mesh,对过大偏移做软压缩
217
+ if (offsetY > 0 && minPixelSize > 0 && offsetY > minPixelSize * 0.5) {
218
+ const base = minPixelSize * 0.3
219
+ offsetY = base + (offsetY - base) * 0.35
206
220
  }
207
221
 
208
- // minimumPixelSize 会让远景模型在屏幕上被抬高,仅用世界高度会产生“飘”感
209
222
  if (minPixelSize > 0) {
210
- offsetY = Math.max(offsetY, minPixelSize * 0.55)
223
+ const visualRoofOffset = minPixelSize * 0.28
224
+ if (offsetY <= 0 || offsetY < visualRoofOffset) {
225
+ offsetY = visualRoofOffset
226
+ }
211
227
  }
212
228
 
213
229
  if (offsetY <= 0) {
214
- offsetY = minPixelSize > 0 ? minPixelSize * 0.55 : 28
230
+ offsetY = minPixelSize > 0 ? minPixelSize * 0.28 : 16
215
231
  }
216
232
 
217
233
  return {
@@ -230,7 +246,8 @@ const resolveBadgeScreenPosition = (scene, basePos, topWorldPos, minPixelSize, p
230
246
  * @param {Function} [options.getVisible] 是否显示信息牌
231
247
  * @param {boolean} [options.isOffline=false] true=离线,false=在线
232
248
  * @param {number} [options.labelOffset=1] 模型未加载完成时的兜底高度(米)
233
- * @param {number} [options.pixelGap=2] 信息牌与车顶之间的像素间距
249
+ * @param {number} [options.pixelGap=0] 信息牌与车顶之间的像素间距
250
+ * @param {number} [options.heightScale=0.72] 屏幕偏移收紧系数(越小越贴近车顶)
234
251
  */
235
252
  export function createGlbInfoBadge(options = {}) {
236
253
  const {
@@ -242,6 +259,7 @@ export function createGlbInfoBadge(options = {}) {
242
259
  isOffline = false,
243
260
  labelOffset = DEFAULT_LABEL_OFFSET,
244
261
  pixelGap = DEFAULT_PIXEL_GAP,
262
+ heightScale = DEFAULT_HEIGHT_SCALE,
245
263
  } = options
246
264
 
247
265
  if (!map || typeof getPosition !== 'function') {
@@ -302,7 +320,8 @@ export function createGlbInfoBadge(options = {}) {
302
320
  basePos,
303
321
  topWorldPos,
304
322
  minPixelSize,
305
- pixelGap
323
+ pixelGap,
324
+ heightScale
306
325
  )
307
326
 
308
327
  if (!screenPos) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huweili-cesium",
3
- "version": "1.2.97",
3
+ "version": "1.2.99",
4
4
  "description": "基于 Cesium 的地图工具库(无人机态势、轨迹、围栏、工具栏等)",
5
5
  "type": "module",
6
6
  "main": "./index.js",