cesium-xs-sdk 1.0.16 → 1.0.17
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/dist/cesium-xs-sdk.cjs.js +134 -2
- package/dist/cesium-xs-sdk.cjs.js.map +1 -1
- package/dist/cesium-xs-sdk.esm.js +134 -2
- package/dist/cesium-xs-sdk.esm.js.map +1 -1
- package/dist/cesium-xs-sdk.umd.js +1 -1
- package/dist/cesium-xs-sdk.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/tools/BaseTool.js +19 -0
- package/src/modules/tools/DrawTool.js +43 -1
- package/src/modules/tools/MeasureTool.js +21 -1
- package/src/utils/DoubleClickDetector.js +51 -0
|
@@ -3566,6 +3566,58 @@ class EventModule {
|
|
|
3566
3566
|
}
|
|
3567
3567
|
}
|
|
3568
3568
|
|
|
3569
|
+
/**
|
|
3570
|
+
* 双击判定器
|
|
3571
|
+
*
|
|
3572
|
+
* 背景:Cesium 的 ScreenSpaceEventType.LEFT_DOUBLE_CLICK 唯一来源是 canvas 上的
|
|
3573
|
+
* DOM dblclick 事件,而 DOM dblclick 依赖浏览器/操作系统的双击合成
|
|
3574
|
+
* (时间阈值 + 位移阈值 + 触屏 touch slop + 双击缩放启发式),移动场景下经常
|
|
3575
|
+
* 不触发,导致"双击结束绘制/测量"在移动端静默失效。
|
|
3576
|
+
*
|
|
3577
|
+
* 本判定器在 SDK 自己的 LEFT_CLICK(mouse:click)流水上自维护双击判定:
|
|
3578
|
+
* 连续两次 click 间隔 < 时间阈值 且 屏幕位移 < 位移阈值,即判定为双击。
|
|
3579
|
+
* 如此双击收尾在鼠标、触屏、任何浏览器上行为一致,彻底移除对 DOM dblclick
|
|
3580
|
+
* 合成的依赖(桌面端 DOM dblclick 路径保留作为冗余,二者靠
|
|
3581
|
+
* _isDrawing / _isMeasuring 守卫天然防重)。
|
|
3582
|
+
*
|
|
3583
|
+
* 阈值取向:宁可漏判(用户多点一下),不可误判(把正常快速加点误判成双击收尾)。
|
|
3584
|
+
*/
|
|
3585
|
+
const DOUBLE_CLICK_INTERVAL_MS = 300; // 时间阈值(ms)
|
|
3586
|
+
const DOUBLE_CLICK_DISTANCE_PX = 10; // 屏幕位移阈值(px)
|
|
3587
|
+
|
|
3588
|
+
class DoubleClickDetector {
|
|
3589
|
+
constructor() {
|
|
3590
|
+
/** @type {{timestamp: number, screenPos: {x: number, y: number}} | null} */
|
|
3591
|
+
this._last = null;
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
/**
|
|
3595
|
+
* 清空内部状态。工具 activate / deactivate / 绘制会话结束 / 取消时调用,
|
|
3596
|
+
* 避免跨工具、跨绘制会话的脏状态污染下一次判定。
|
|
3597
|
+
*/
|
|
3598
|
+
reset() {
|
|
3599
|
+
this._last = null;
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
/**
|
|
3603
|
+
* 喂入一次 click,返回是否构成双击。
|
|
3604
|
+
* 注意:无论是否构成双击,本次点击都会成为下次判定的"上一次点击"。
|
|
3605
|
+
*
|
|
3606
|
+
* @param {number} timestamp performance.now()
|
|
3607
|
+
* @param {{x: number, y: number}} screenPos 屏幕坐标(取 movement.position)
|
|
3608
|
+
* @returns {boolean} 是否构成双击
|
|
3609
|
+
*/
|
|
3610
|
+
feed(timestamp, screenPos) {
|
|
3611
|
+
const prev = this._last;
|
|
3612
|
+
this._last = { timestamp, screenPos };
|
|
3613
|
+
if (!prev) return false;
|
|
3614
|
+
if (timestamp - prev.timestamp > DOUBLE_CLICK_INTERVAL_MS) return false;
|
|
3615
|
+
const dx = screenPos.x - prev.screenPos.x;
|
|
3616
|
+
const dy = screenPos.y - prev.screenPos.y;
|
|
3617
|
+
return Math.hypot(dx, dy) <= DOUBLE_CLICK_DISTANCE_PX;
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
|
|
3569
3621
|
const Cesium$d = getCesium();
|
|
3570
3622
|
|
|
3571
3623
|
/**
|
|
@@ -3581,6 +3633,8 @@ class BaseTool {
|
|
|
3581
3633
|
this._options = options;
|
|
3582
3634
|
this._isActive = false;
|
|
3583
3635
|
this._handlers = []; // 注册的事件处理器 ID
|
|
3636
|
+
// 自维护双击判定器(DOM dblclick 在移动端经常不合成,见 DoubleClickDetector 注释)
|
|
3637
|
+
this._doubleClickDetector = new DoubleClickDetector();
|
|
3584
3638
|
}
|
|
3585
3639
|
|
|
3586
3640
|
/**
|
|
@@ -3589,6 +3643,8 @@ class BaseTool {
|
|
|
3589
3643
|
activate() {
|
|
3590
3644
|
if (this._isActive) return;
|
|
3591
3645
|
this._isActive = true;
|
|
3646
|
+
// 防止跨工具切换时残留上次会话的末次点击,污染本次双击判定
|
|
3647
|
+
this._doubleClickDetector.reset();
|
|
3592
3648
|
this.onActivate();
|
|
3593
3649
|
}
|
|
3594
3650
|
|
|
@@ -3598,6 +3654,7 @@ class BaseTool {
|
|
|
3598
3654
|
deactivate() {
|
|
3599
3655
|
if (!this._isActive) return;
|
|
3600
3656
|
this._isActive = false;
|
|
3657
|
+
this._doubleClickDetector.reset();
|
|
3601
3658
|
this.onDeactivate();
|
|
3602
3659
|
this.clearHandlers();
|
|
3603
3660
|
}
|
|
@@ -3612,6 +3669,19 @@ class BaseTool {
|
|
|
3612
3669
|
*/
|
|
3613
3670
|
onDeactivate() { }
|
|
3614
3671
|
|
|
3672
|
+
/**
|
|
3673
|
+
* 判定本次 mouse:click 是否构成"双击"(自维护判定,不依赖 DOM dblclick 合成)。
|
|
3674
|
+
* 子类应在"绘制 / 测量进行中"才调用本方法,避免把开启新会话的首次点击误判为双击。
|
|
3675
|
+
* @param {object} movement Cesium click 事件 movement(取 movement.position 作为屏幕坐标)
|
|
3676
|
+
* @returns {boolean}
|
|
3677
|
+
* @protected
|
|
3678
|
+
*/
|
|
3679
|
+
_isDoubleClick(movement) {
|
|
3680
|
+
const pos = movement && movement.position;
|
|
3681
|
+
if (!pos) return false;
|
|
3682
|
+
return this._doubleClickDetector.feed(performance.now(), { x: pos.x, y: pos.y });
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3615
3685
|
/**
|
|
3616
3686
|
* 注册事件观察者
|
|
3617
3687
|
* @param {string} eventType 事件类型
|
|
@@ -3941,8 +4011,30 @@ class DrawTool extends BaseTool {
|
|
|
3941
4011
|
// lngLat 已经是经纬度数组 [lon, lat, height]
|
|
3942
4012
|
if (!lngLat) return;
|
|
3943
4013
|
|
|
3944
|
-
// 优先处理标绘类型
|
|
3945
4014
|
const plotConfig = PLOT_DRAW_CONFIG[this._drawType];
|
|
4015
|
+
|
|
4016
|
+
// === 自维护双击收尾判定 ===
|
|
4017
|
+
// DOM dblclick 在移动端/触屏经常不被浏览器合成(见 change-log),这里在
|
|
4018
|
+
// LEFT_CLICK 流水上自行判定:绘制中 + 类型支持双击收尾 + 两次 click
|
|
4019
|
+
// 时间/位移在阈值内 → 收尾。本次(双击第二次)点击不加点——双击第一次
|
|
4020
|
+
// 点击已把最后顶点加入 _tempPositions,直接收尾的结果与 DOM dblclick
|
|
4021
|
+
// 路径(_onDoubleClick pop 掉重叠点)逐点一致。
|
|
4022
|
+
// 不满足最小点数时降级为普通加点,落到下方正常逻辑。
|
|
4023
|
+
if (this._isDrawing && this._supportsDoubleClickFinish() && this._isDoubleClick(movement)) {
|
|
4024
|
+
const minPoints = plotConfig ? plotConfig.minPoints
|
|
4025
|
+
: (this._drawType === DrawType.POLYGON ? 3 : 2); // 线 2 / 面 3
|
|
4026
|
+
if (this._tempPositions.length >= minPoints) {
|
|
4027
|
+
if (plotConfig) {
|
|
4028
|
+
this._finishPlotDrawing(plotConfig);
|
|
4029
|
+
} else {
|
|
4030
|
+
this.finishDrawing();
|
|
4031
|
+
}
|
|
4032
|
+
return;
|
|
4033
|
+
}
|
|
4034
|
+
// 不满足最小点数:本次点击降级为普通加点(落到下方逻辑)
|
|
4035
|
+
}
|
|
4036
|
+
|
|
4037
|
+
// 优先处理标绘类型
|
|
3946
4038
|
if (plotConfig) {
|
|
3947
4039
|
this._handlePlotClick(lngLat, plotConfig);
|
|
3948
4040
|
return;
|
|
@@ -4082,6 +4174,18 @@ class DrawTool extends BaseTool {
|
|
|
4082
4174
|
}
|
|
4083
4175
|
}
|
|
4084
4176
|
|
|
4177
|
+
/**
|
|
4178
|
+
* 当前绘制类型是否支持"双击收尾":
|
|
4179
|
+
* 仅线 / 面 / 声明了 finishOnDoubleClick 的标绘类型支持;
|
|
4180
|
+
* 点 / 矩形 / 圆保持不响应(与 _onDoubleClick 的语义一致)。
|
|
4181
|
+
* @private
|
|
4182
|
+
*/
|
|
4183
|
+
_supportsDoubleClickFinish() {
|
|
4184
|
+
if (this._drawType === DrawType.LINE || this._drawType === DrawType.POLYGON) return true;
|
|
4185
|
+
const plotConfig = PLOT_DRAW_CONFIG[this._drawType];
|
|
4186
|
+
return !!(plotConfig && plotConfig.finishOnDoubleClick);
|
|
4187
|
+
}
|
|
4188
|
+
|
|
4085
4189
|
/**
|
|
4086
4190
|
* 双击结束绘制(移动端用:移动端没有右键;桌面端:避免绘制过程中双击误触发放大)
|
|
4087
4191
|
* 与 _onRightClick 等价,仅线 / 面 / 标绘(声明了 finishOnDoubleClick 的)响应;
|
|
@@ -4747,6 +4851,9 @@ class DrawTool extends BaseTool {
|
|
|
4747
4851
|
this._tempPositions = [];
|
|
4748
4852
|
this._previewPlot = null;
|
|
4749
4853
|
|
|
4854
|
+
// 绘制会话结束:清空双击判定器,避免下次绘制的开头点击与本次末次点击构成误判
|
|
4855
|
+
this._doubleClickDetector.reset();
|
|
4856
|
+
|
|
4750
4857
|
this._emitGraphicCreated(config.plotType, id);
|
|
4751
4858
|
}
|
|
4752
4859
|
|
|
@@ -4778,6 +4885,8 @@ class DrawTool extends BaseTool {
|
|
|
4778
4885
|
this._clickCount = 0;
|
|
4779
4886
|
this._startPos = null;
|
|
4780
4887
|
this._currentMousePos = null;
|
|
4888
|
+
// 绘制会话取消:清空双击判定器,避免下次绘制受本次末次点击污染
|
|
4889
|
+
this._doubleClickDetector.reset();
|
|
4781
4890
|
this._emitDrawCancel();
|
|
4782
4891
|
}
|
|
4783
4892
|
|
|
@@ -4833,6 +4942,9 @@ class DrawTool extends BaseTool {
|
|
|
4833
4942
|
this._clickCount = 0;
|
|
4834
4943
|
this._currentMousePos = null;
|
|
4835
4944
|
|
|
4945
|
+
// 绘制会话结束:清空双击判定器,避免下次绘制的开头点击与本次末次点击构成误判
|
|
4946
|
+
this._doubleClickDetector.reset();
|
|
4947
|
+
|
|
4836
4948
|
if (deferredPreviewLine) {
|
|
4837
4949
|
requestAnimationFrame(() => this.removeTempEntity(deferredPreviewLine));
|
|
4838
4950
|
}
|
|
@@ -7734,7 +7846,7 @@ class MeasureTool extends BaseTool {
|
|
|
7734
7846
|
controller.enableRotate = this._originalEnableRotate;
|
|
7735
7847
|
}
|
|
7736
7848
|
|
|
7737
|
-
_onClick(lngLat, _pickedEntity,
|
|
7849
|
+
_onClick(lngLat, _pickedEntity, movement) {
|
|
7738
7850
|
if (!lngLat) return;
|
|
7739
7851
|
|
|
7740
7852
|
// 拖拽刚结束:吞掉紧跟 mouseup 的 click,避免误开新测量
|
|
@@ -7743,6 +7855,21 @@ class MeasureTool extends BaseTool {
|
|
|
7743
7855
|
return;
|
|
7744
7856
|
}
|
|
7745
7857
|
|
|
7858
|
+
// === 自维护双击收尾判定 ===
|
|
7859
|
+
// DOM dblclick 在移动端/触屏经常不被浏览器合成(见 change-log),这里在
|
|
7860
|
+
// LEFT_CLICK 流水上自行判定:测量中(非拖拽中)+ 两次 click 时间/位移在
|
|
7861
|
+
// 阈值内 → 收尾。本次(双击第二次)点击不加点——双击第一次点击已把最后
|
|
7862
|
+
// 顶点加入 _positions,直接收尾的结果与 DOM dblclick 路径(_onDoubleClick
|
|
7863
|
+
// pop 掉重叠点)逐点一致。不满足最小点数时降级为普通加点。
|
|
7864
|
+
if (this._isMeasuring && !this._isDragging && this._isDoubleClick(movement)) {
|
|
7865
|
+
const minPoints = this._measureType === MeasureType.AREA ? 3 : 2;
|
|
7866
|
+
if (this._positions.length >= minPoints) {
|
|
7867
|
+
this._finishMeasurement();
|
|
7868
|
+
return;
|
|
7869
|
+
}
|
|
7870
|
+
// 不满足最小点数:本次点击降级为普通加点(落到下方逻辑)
|
|
7871
|
+
}
|
|
7872
|
+
|
|
7746
7873
|
// 同步鼠标位置为本次 click 的经纬度:修复"地图拖动后原地点击 → 预览线
|
|
7747
7874
|
// 自动连接到旧鼠标位置"的 bug(主要暴露在移动端双击完成测量后)。
|
|
7748
7875
|
//
|
|
@@ -7981,6 +8108,9 @@ class MeasureTool extends BaseTool {
|
|
|
7981
8108
|
// 测量已完成 → 恢复地图拖动 / 旋转
|
|
7982
8109
|
this._restoreCameraAfterMeasuring();
|
|
7983
8110
|
|
|
8111
|
+
// 测量会话结束:清空双击判定器,避免下次测量受本次末次点击污染
|
|
8112
|
+
this._doubleClickDetector.reset();
|
|
8113
|
+
|
|
7984
8114
|
this._emitMeasureComplete(result);
|
|
7985
8115
|
}
|
|
7986
8116
|
|
|
@@ -8082,6 +8212,8 @@ class MeasureTool extends BaseTool {
|
|
|
8082
8212
|
this.clearMeasurements();
|
|
8083
8213
|
// 取消时也要恢复地图拖动(与 _finishMeasurement 对称)
|
|
8084
8214
|
this._restoreCameraAfterMeasuring();
|
|
8215
|
+
// 测量会话取消:清空双击判定器,避免下次测量受本次末次点击污染
|
|
8216
|
+
this._doubleClickDetector.reset();
|
|
8085
8217
|
this._emitMeasureCancel();
|
|
8086
8218
|
}
|
|
8087
8219
|
|