cesium-xs-sdk 1.0.18 → 1.0.19

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.
@@ -845,6 +845,24 @@ class SceneModule {
845
845
  }
846
846
  });
847
847
  }
848
+
849
+ /**
850
+ * 是否开启南北极轴约束
851
+ * 开启时(Cesium 默认行为)鼠标旋转/缩放无法让相机越过南北极点;
852
+ * 关闭时(viewer.camera.constrainedAxis = undefined)相机可穿越极点。
853
+ * @param {boolean} [enabled=true] true 开启约束,false 关闭约束
854
+ */
855
+ setPolarAxisConstraint(enabled = true) {
856
+ this.viewer.camera.constrainedAxis = enabled ? Cesium$h.Cartesian3.UNIT_Z : undefined;
857
+ }
858
+
859
+ /**
860
+ * 查询南北极轴约束是否开启
861
+ * @returns {boolean} true 已开启(相机不可穿越极点),false 已关闭
862
+ */
863
+ isPolarAxisConstraintEnabled() {
864
+ return Cesium$h.defined(this.viewer.camera.constrainedAxis);
865
+ }
848
866
  }
849
867
 
850
868
  const Cesium$g = getCesium();
@@ -10054,9 +10072,15 @@ class Zoom extends BaseControl {
10054
10072
  const camera = this._viewer.camera;
10055
10073
  // 以双击位置拾取到的地表点为缩放中心;拾取不到退回相机正下方
10056
10074
  let cartographic = camera.positionCartographic;
10075
+ // 锚点缩放需要"点击像素的视线方向":保持这条视线不变,
10076
+ // 锚点缩放后才仍投影在光标下方(相机中轴方向只在点击点恰为中心时成立)
10077
+ let rayDirection = camera.direction;
10057
10078
  if (movement?.position && this._viewer.scene?.globe) {
10058
10079
  const ray = camera.getPickRay(movement.position);
10059
10080
  const cartesian = ray ? this._viewer.scene.globe.pick(ray, this._viewer.scene) : null;
10081
+ if (ray) {
10082
+ rayDirection = ray.direction;
10083
+ }
10060
10084
  if (cartesian) {
10061
10085
  cartographic = Cesium$5.Cartographic.fromCartesian(cartesian);
10062
10086
  }
@@ -10064,7 +10088,89 @@ class Zoom extends BaseControl {
10064
10088
 
10065
10089
  const currentLevel = this._pendingLevel ?? this._getZoomLevel();
10066
10090
  const targetLevel = Math.max(0, Math.min(24, currentLevel + levelDelta));
10067
- this._flyToLevel(targetLevel, cartographic);
10091
+ this._flyToLevelKeepScreenPoint(targetLevel, cartographic, rayDirection);
10092
+ }
10093
+
10094
+ /**
10095
+ * 飞到指定层级,且保持 cartographic 对应的地面点在原屏幕位置(锚点缩放)。
10096
+ *
10097
+ * 与 _flyToLevel(以点为中心)不同:这里把相机沿"点击像素的视线方向"反方向
10098
+ * 退到目标高度——同一像素的视线方向只取决于相机姿态、与位置无关,因此相机
10099
+ * 沿该方向移动后,锚点仍投影在双击位置(光标下方),而不是被搬到屏幕中心。
10100
+ * 视线几乎水平(点击靠近地平线/天空)时退化为居中模式。
10101
+ *
10102
+ * @param {number} targetLevel 目标层级
10103
+ * @param {Cesium.Cartographic} cartographic 锚点(双击拾取的地面点)
10104
+ * @param {Cesium.Cartesian3} rayDirection 点击像素的视线方向(ECEF 单位向量)
10105
+ */
10106
+ _flyToLevelKeepScreenPoint(targetLevel, cartographic, rayDirection) {
10107
+ const camera = this._viewer.camera;
10108
+ const targetHeight = this._getHeightByZoomLevel(targetLevel);
10109
+ const pitch = camera.pitch;
10110
+
10111
+ let destination = null;
10112
+ // 相机俯角至少 ~60° 才做锚点缩放;更平时后退距离发散,观感也差,退化为中心模式
10113
+ const minPitch = Cesium$5.Math.toRadians(-60);
10114
+ if (pitch <= minPitch && rayDirection) {
10115
+ // 锚点处的本地"上"方向(ECEF)
10116
+ const cosLat = Math.cos(cartographic.latitude);
10117
+ const up = new Cesium$5.Cartesian3(
10118
+ cosLat * Math.cos(cartographic.longitude),
10119
+ cosLat * Math.sin(cartographic.longitude),
10120
+ Math.sin(cartographic.latitude)
10121
+ );
10122
+ // 视线向下的分量
10123
+ const rayUp = Cesium$5.Cartesian3.dot(rayDirection, up);
10124
+ // 相机沿视线到锚点的距离:垂直落差 / 视线向下分量
10125
+ const s = (targetHeight - cartographic.height) / (-rayUp);
10126
+ if (rayUp < -0.05 && Number.isFinite(s) && s > 0) {
10127
+ const anchor = Cesium$5.Cartesian3.fromRadians(
10128
+ cartographic.longitude,
10129
+ cartographic.latitude,
10130
+ cartographic.height
10131
+ );
10132
+ destination = Cesium$5.Cartesian3.add(
10133
+ anchor,
10134
+ Cesium$5.Cartesian3.multiplyByScalar(rayDirection, -s, new Cesium$5.Cartesian3()),
10135
+ new Cesium$5.Cartesian3()
10136
+ );
10137
+ }
10138
+ }
10139
+
10140
+ if (!destination) {
10141
+ destination = Cesium$5.Cartesian3.fromRadians(
10142
+ cartographic.longitude,
10143
+ cartographic.latitude,
10144
+ targetHeight
10145
+ );
10146
+ }
10147
+ this._flyToDestination(targetLevel, destination);
10148
+ }
10149
+
10150
+ /**
10151
+ * 飞到指定层级的目的地(目的地构造交给调用方),并记录 _pendingLevel
10152
+ * @param {number} targetLevel 目标层级
10153
+ * @param {Cesium.Cartesian3} destination 相机最终位置
10154
+ */
10155
+ _flyToDestination(targetLevel, destination) {
10156
+ const camera = this._viewer.camera;
10157
+
10158
+ this._pendingLevel = targetLevel;
10159
+ camera.flyTo({
10160
+ destination,
10161
+ orientation: {
10162
+ heading: camera.heading,
10163
+ pitch: camera.pitch,
10164
+ roll: camera.roll
10165
+ },
10166
+ duration: this._duration,
10167
+ complete: () => {
10168
+ if (this._pendingLevel === targetLevel) this._pendingLevel = null;
10169
+ },
10170
+ cancel: () => {
10171
+ if (this._pendingLevel === targetLevel) this._pendingLevel = null;
10172
+ }
10173
+ });
10068
10174
  }
10069
10175
 
10070
10176
  _zoomIn() {
@@ -10086,34 +10192,19 @@ class Zoom extends BaseControl {
10086
10192
  }
10087
10193
 
10088
10194
  /**
10089
- * 飞到指定层级(以给定经纬度为中心),并记录 _pendingLevel
10195
+ * 飞到指定层级(以给定经纬度为正下方中心),并记录 _pendingLevel
10090
10196
  * @param {number} targetLevel 目标层级
10091
10197
  * @param {Cesium.Cartographic} cartographic 目的地中心
10092
10198
  */
10093
10199
  _flyToLevel(targetLevel, cartographic) {
10094
- const camera = this._viewer.camera;
10095
- const targetHeight = this._getHeightByZoomLevel(targetLevel);
10096
-
10097
- this._pendingLevel = targetLevel;
10098
- camera.flyTo({
10099
- destination: Cesium$5.Cartesian3.fromRadians(
10200
+ this._flyToDestination(
10201
+ targetLevel,
10202
+ Cesium$5.Cartesian3.fromRadians(
10100
10203
  cartographic.longitude,
10101
10204
  cartographic.latitude,
10102
- targetHeight
10103
- ),
10104
- orientation: {
10105
- heading: camera.heading,
10106
- pitch: camera.pitch,
10107
- roll: camera.roll
10108
- },
10109
- duration: this._duration,
10110
- complete: () => {
10111
- if (this._pendingLevel === targetLevel) this._pendingLevel = null;
10112
- },
10113
- cancel: () => {
10114
- if (this._pendingLevel === targetLevel) this._pendingLevel = null;
10115
- }
10116
- });
10205
+ this._getHeightByZoomLevel(targetLevel)
10206
+ )
10207
+ );
10117
10208
  }
10118
10209
 
10119
10210
  _getZoomLevel() {