@jorgmoritz/gis-manager 0.1.37 → 0.1.39

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.
@@ -1551,7 +1551,7 @@ var CameraFOVController = class {
1551
1551
  this.minFOV = opts.minFOV;
1552
1552
  this.maxFOV = opts.maxFOV;
1553
1553
  }
1554
- this.currentFOV = opts.initialFOV ?? this.focalLengthToFOVDirect(56);
1554
+ this.currentFOV = opts.initialFOV ?? this.focalLengthToFOVDirect(1);
1555
1555
  this.useGlobalEventBus = opts.useGlobalEventBus ?? true;
1556
1556
  this.createUI();
1557
1557
  this.setupExternalFOVListener();
@@ -1901,7 +1901,7 @@ var CameraFOVController = class {
1901
1901
 
1902
1902
  // src/core/path-manager/PathPreview.ts
1903
1903
  var PathPreview = class {
1904
- // 当前 FOV 值
1904
+ // 折叠按钮
1905
1905
  constructor(CesiumNS, mainViewer, opts = {}) {
1906
1906
  this.CesiumNS = CesiumNS;
1907
1907
  this.mainViewer = mainViewer;
@@ -1917,6 +1917,10 @@ var PathPreview = class {
1917
1917
  __publicField(this, "fovController");
1918
1918
  // FOV 控制器
1919
1919
  __publicField(this, "currentFOV");
1920
+ // 当前 FOV 值
1921
+ __publicField(this, "collapsed", false);
1922
+ // 折叠状态
1923
+ __publicField(this, "toggleBtn");
1920
1924
  /** 已加载的 3D Tiles 实例(预览窗口独立的) */
1921
1925
  __publicField(this, "tilesets", /* @__PURE__ */ new Map());
1922
1926
  this.currentFOV = opts.fov ?? 50;
@@ -1931,9 +1935,9 @@ var PathPreview = class {
1931
1935
  host = document.createElement("div");
1932
1936
  host.style.position = "absolute";
1933
1937
  host.style.right = "10px";
1934
- host.style.bottom = "10px";
1935
- host.style.width = "480px";
1936
- host.style.height = "320px";
1938
+ host.style.bottom = "80px";
1939
+ host.style.width = "320px";
1940
+ host.style.height = "200px";
1937
1941
  host.style.border = "1px solid rgba(255, 255, 255, 1)";
1938
1942
  host.style.borderRadius = "6px";
1939
1943
  host.style.overflow = "hidden";
@@ -1943,6 +1947,7 @@ var PathPreview = class {
1943
1947
  parent?.appendChild(host);
1944
1948
  } catch {
1945
1949
  }
1950
+ this.createToggleButton(host);
1946
1951
  }
1947
1952
  this.containerEl = host;
1948
1953
  const v = new C.Viewer(host, {
@@ -1977,6 +1982,157 @@ var PathPreview = class {
1977
1982
  this.syncFromMainViewer();
1978
1983
  this.disableUserInteraction();
1979
1984
  }
1985
+ /**
1986
+ * 创建折叠按钮
1987
+ */
1988
+ createToggleButton(container) {
1989
+ if (typeof document === "undefined") return;
1990
+ this.toggleBtn = document.createElement("div");
1991
+ this.toggleBtn.style.cssText = `
1992
+ position: absolute;
1993
+ top: 6px;
1994
+ left: 6px;
1995
+ width: 24px;
1996
+ height: 24px;
1997
+ background: rgba(0, 0, 0, 0.6);
1998
+ border: 1px solid rgba(255, 255, 255, 0.5);
1999
+ border-radius: 4px;
2000
+ cursor: pointer;
2001
+ z-index: 20;
2002
+ display: flex;
2003
+ align-items: center;
2004
+ justify-content: center;
2005
+ transition: all 0.2s;
2006
+ pointer-events: auto;
2007
+ `;
2008
+ this.toggleBtn.innerHTML = `
2009
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="white" style="transition: transform 0.2s;">
2010
+ <path d="M4 2 L8 6 L4 10" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
2011
+ </svg>
2012
+ `;
2013
+ this.toggleBtn.addEventListener("mouseenter", () => {
2014
+ if (this.toggleBtn) {
2015
+ this.toggleBtn.style.background = "rgba(47, 119, 251, 0.8)";
2016
+ }
2017
+ });
2018
+ this.toggleBtn.addEventListener("mouseleave", () => {
2019
+ if (this.toggleBtn) {
2020
+ this.toggleBtn.style.background = "rgba(0, 0, 0, 0.6)";
2021
+ }
2022
+ });
2023
+ this.toggleBtn.addEventListener("click", (e) => {
2024
+ e.stopPropagation();
2025
+ this.toggle();
2026
+ });
2027
+ container.appendChild(this.toggleBtn);
2028
+ }
2029
+ /**
2030
+ * 切换折叠状态
2031
+ */
2032
+ toggle() {
2033
+ if (this.collapsed) {
2034
+ this.expand();
2035
+ } else {
2036
+ this.collapse();
2037
+ }
2038
+ }
2039
+ /**
2040
+ * 折叠预览窗口
2041
+ */
2042
+ collapse() {
2043
+ if (this.collapsed || !this.containerEl) return;
2044
+ this.collapsed = true;
2045
+ this.containerEl.dataset.originalWidth = this.containerEl.style.width;
2046
+ this.containerEl.dataset.originalHeight = this.containerEl.style.height;
2047
+ this.containerEl.style.width = "36px";
2048
+ this.containerEl.style.height = "36px";
2049
+ this.containerEl.style.overflow = "hidden";
2050
+ if (this.overlayViewer) {
2051
+ const viewerContainer = this.overlayViewer.container;
2052
+ if (viewerContainer) {
2053
+ viewerContainer.style.display = "none";
2054
+ }
2055
+ }
2056
+ this.hideFOVController();
2057
+ if (this.toggleBtn) {
2058
+ this.toggleBtn.style.cssText = `
2059
+ position: absolute;
2060
+ top: 2px;
2061
+ left: 2px;
2062
+ right: 2px;
2063
+ bottom: 2px;
2064
+ width: auto;
2065
+ height: auto;
2066
+ background: rgba(47, 119, 251, 0.9);
2067
+ border: 1px solid rgba(255, 255, 255, 0.8);
2068
+ border-radius: 4px;
2069
+ cursor: pointer;
2070
+ z-index: 20;
2071
+ display: flex;
2072
+ align-items: center;
2073
+ justify-content: center;
2074
+ transition: all 0.2s;
2075
+ pointer-events: auto;
2076
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
2077
+ `;
2078
+ this.toggleBtn.innerHTML = `
2079
+ <svg width="16" height="16" viewBox="0 0 12 12" fill="white">
2080
+ <path d="M8 2 L4 6 L8 10" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
2081
+ </svg>
2082
+ `;
2083
+ }
2084
+ this.containerEl.style.display = "block";
2085
+ }
2086
+ /**
2087
+ * 展开预览窗口
2088
+ */
2089
+ expand() {
2090
+ if (!this.collapsed || !this.containerEl) return;
2091
+ this.collapsed = false;
2092
+ this.containerEl.style.width = this.containerEl.dataset.originalWidth || "320px";
2093
+ this.containerEl.style.height = this.containerEl.dataset.originalHeight || "200px";
2094
+ if (this.overlayViewer) {
2095
+ const viewerContainer = this.overlayViewer.container;
2096
+ if (viewerContainer) {
2097
+ viewerContainer.style.display = "block";
2098
+ }
2099
+ }
2100
+ this.showFOVController();
2101
+ if (this.toggleBtn) {
2102
+ this.toggleBtn.style.cssText = `
2103
+ position: absolute;
2104
+ top: 6px;
2105
+ left: 6px;
2106
+ width: 24px;
2107
+ height: 24px;
2108
+ background: rgba(0, 0, 0, 0.6);
2109
+ border: 1px solid rgba(255, 255, 255, 0.5);
2110
+ border-radius: 4px;
2111
+ cursor: pointer;
2112
+ z-index: 20;
2113
+ display: flex;
2114
+ align-items: center;
2115
+ justify-content: center;
2116
+ transition: all 0.2s;
2117
+ pointer-events: auto;
2118
+ `;
2119
+ this.toggleBtn.innerHTML = `
2120
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="white">
2121
+ <path d="M4 2 L8 6 L4 10" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
2122
+ </svg>
2123
+ `;
2124
+ }
2125
+ try {
2126
+ this.overlayViewer?.scene?.requestRender?.();
2127
+ } catch {
2128
+ }
2129
+ }
2130
+ /**
2131
+ * 获取折叠状态
2132
+ */
2133
+ isCollapsed() {
2134
+ return this.collapsed;
2135
+ }
1980
2136
  /**
1981
2137
  * 从主 viewer 同步配置
1982
2138
  * 共享 Provider(安全)而非 DataSource
@@ -2363,6 +2519,11 @@ var PathPreview = class {
2363
2519
  }
2364
2520
  this.fovController = void 0;
2365
2521
  this.footprintEntity = void 0;
2522
+ try {
2523
+ this.toggleBtn?.remove();
2524
+ } catch {
2525
+ }
2526
+ this.toggleBtn = void 0;
2366
2527
  try {
2367
2528
  this.tilesets.forEach((tileset) => {
2368
2529
  try {
@@ -2799,7 +2960,7 @@ var AirplaneCursor = class {
2799
2960
  this.step = opts.stepMeters ?? 2;
2800
2961
  this.angleStep = opts.angleStepDeg ?? 1;
2801
2962
  this.fastFactor = opts.fastFactor ?? 5;
2802
- this.currentFOV = opts.fovDeg ?? 50;
2963
+ this.currentFOV = opts.fovDeg ?? 172;
2803
2964
  this.ensureEntity(opts.color ?? C.Color.CYAN.withAlpha(0.9));
2804
2965
  this.attachKeyboard(opts);
2805
2966
  this.setupFOVListener();
@@ -3077,7 +3238,8 @@ var AirplaneCursor = class {
3077
3238
  this.viewer.dataSources.add(layer);
3078
3239
  }
3079
3240
  this.frustum = new FrustumPyramid(this.CesiumNS, layer, {
3080
- fov: this.opts.fovDeg ?? 40,
3241
+ fov: this.opts.fovDeg ?? 172,
3242
+ // 默认 1mm 焦距对应的 FOV
3081
3243
  length: 80,
3082
3244
  color: this.opts.color,
3083
3245
  fillAlpha: 0.25,
@@ -8250,7 +8412,9 @@ var PolygonEditor = class {
8250
8412
  polygon: {
8251
8413
  hierarchy: positions,
8252
8414
  material: faceColor,
8253
- outline: false
8415
+ outline: false,
8416
+ // 🔧 修复:设置 heightReference 使多边形贴合地形
8417
+ heightReference: C.HeightReference.CLAMP_TO_GROUND
8254
8418
  }
8255
8419
  });
8256
8420
  const ring = positions.slice();
@@ -8263,15 +8427,51 @@ var PolygonEditor = class {
8263
8427
  width: 1,
8264
8428
  material: lineColor,
8265
8429
  clampToGround: true
8430
+ // 轮廓线已经设置了 clampToGround
8266
8431
  },
8267
8432
  properties: { _ownerId: id, _type: "polygon-outline" }
8268
8433
  });
8269
8434
  this.applyDashedOutlineStyle(outlineEntity, lineColor, 3, 10);
8270
8435
  const displayText = name.includes("_") ? name.split("_")[1] : name;
8436
+ const firstPoint = points[0];
8437
+ this.createLabelWithTerrainHeight(
8438
+ layer,
8439
+ id,
8440
+ displayText,
8441
+ firstPoint.lon,
8442
+ firstPoint.lat,
8443
+ lineColor
8444
+ );
8445
+ return entity;
8446
+ } catch (err) {
8447
+ console.error(`[PolygonEditor] \u521B\u5EFA\u591A\u8FB9\u5F62\u5931\u8D25:`, err);
8448
+ return null;
8449
+ }
8450
+ }
8451
+ /**
8452
+ * 辅助方法:使用地形采样创建标签
8453
+ * 先尝试获取地形高度,如果失败则使用 heightReference
8454
+ */
8455
+ async createLabelWithTerrainHeight(layer, ownerId, displayText, lon, lat, lineColor) {
8456
+ const C = this.CesiumNS;
8457
+ try {
8458
+ let terrainHeight = 0;
8459
+ const terrainProvider = this.viewer.terrainProvider;
8460
+ if (terrainProvider && typeof C.sampleTerrainMostDetailed === "function") {
8461
+ try {
8462
+ const positions = [C.Cartographic.fromDegrees(lon, lat)];
8463
+ const updatedPositions = await C.sampleTerrainMostDetailed(terrainProvider, positions);
8464
+ if (updatedPositions && updatedPositions[0] && updatedPositions[0].height !== void 0) {
8465
+ terrainHeight = updatedPositions[0].height;
8466
+ }
8467
+ } catch (e) {
8468
+ }
8469
+ }
8470
+ const labelPosition = C.Cartesian3.fromDegrees(lon, lat, terrainHeight + 1);
8271
8471
  layer.entities.add({
8272
- id: `${id}-label`,
8472
+ id: `${ownerId}-label`,
8273
8473
  name: "Polygon Label",
8274
- position: positions[0],
8474
+ position: labelPosition,
8275
8475
  label: {
8276
8476
  text: displayText,
8277
8477
  font: "bold 16px Microsoft YaHei, SimHei, sans-serif",
@@ -8281,14 +8481,14 @@ var PolygonEditor = class {
8281
8481
  style: C.LabelStyle.FILL_AND_OUTLINE,
8282
8482
  verticalOrigin: C.VerticalOrigin.BOTTOM,
8283
8483
  pixelOffset: new C.Cartesian2(0, -10),
8284
- disableDepthTestDistance: Number.POSITIVE_INFINITY
8484
+ disableDepthTestDistance: Number.POSITIVE_INFINITY,
8485
+ // 仍然设置 heightReference 作为备用
8486
+ heightReference: C.HeightReference.CLAMP_TO_GROUND
8285
8487
  },
8286
- properties: { _ownerId: id, _type: "polygon-label" }
8488
+ properties: { _ownerId: ownerId, _type: "polygon-label" }
8287
8489
  });
8288
- return entity;
8289
- } catch (err) {
8290
- console.error(`[PolygonEditor] \u521B\u5EFA\u591A\u8FB9\u5F62\u5931\u8D25:`, err);
8291
- return null;
8490
+ } catch (e) {
8491
+ console.warn(`[PolygonEditor] \u521B\u5EFA\u6807\u7B7E\u5931\u8D25:`, e);
8292
8492
  }
8293
8493
  }
8294
8494
  /**