cesium-xs-sdk 1.0.13 → 1.0.15
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 +311 -46
- package/dist/cesium-xs-sdk.cjs.js.map +1 -1
- package/dist/cesium-xs-sdk.esm.js +311 -46
- 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/index.d.ts +2 -1
- package/src/modules/GraphicModule.js +19 -2
- package/src/modules/MilitarySymbolModule.js +263 -36
- package/src/modules/militarySymbolAssets.js +37 -10
|
@@ -3198,15 +3198,32 @@ class GraphicModule {
|
|
|
3198
3198
|
const positions = this._getEntityPositions(entity);
|
|
3199
3199
|
if (positions.length < 3) return false;
|
|
3200
3200
|
|
|
3201
|
-
const closedPositions = [...positions, positions[0]];
|
|
3202
3201
|
const outlineId = `${graphicId}_outline`;
|
|
3203
3202
|
const color = options.color ?? Cesium$f.Color.WHITE;
|
|
3204
3203
|
const width = options.width ?? 2;
|
|
3205
3204
|
|
|
3205
|
+
// 用 CallbackProperty 实时跟随主 polygon 的 hierarchy,
|
|
3206
|
+
// 这样 SDK 内部 EditTool 拖拽顶点时,外边框会自动跟随移动。
|
|
3207
|
+
const mainEntity = entity;
|
|
3208
|
+
const positionsCallback = new Cesium$f.CallbackProperty(() => {
|
|
3209
|
+
const hierarchy = mainEntity.polygon?.hierarchy;
|
|
3210
|
+
if (!hierarchy) return [];
|
|
3211
|
+
let positions;
|
|
3212
|
+
if (typeof hierarchy.getValue === 'function') {
|
|
3213
|
+
const value = hierarchy.getValue(Cesium$f.JulianDate.now());
|
|
3214
|
+
positions = value?.positions || [];
|
|
3215
|
+
} else {
|
|
3216
|
+
positions = hierarchy.positions || [];
|
|
3217
|
+
}
|
|
3218
|
+
if (!positions || positions.length < 3) return positions || [];
|
|
3219
|
+
// 闭合:首点再加到末尾
|
|
3220
|
+
return [...positions, positions[0]];
|
|
3221
|
+
}, false);
|
|
3222
|
+
|
|
3206
3223
|
this.viewer.entities.add({
|
|
3207
3224
|
id: outlineId,
|
|
3208
3225
|
polyline: {
|
|
3209
|
-
positions:
|
|
3226
|
+
positions: positionsCallback,
|
|
3210
3227
|
width,
|
|
3211
3228
|
material: color,
|
|
3212
3229
|
clampToGround: true,
|
|
@@ -9198,17 +9215,38 @@ class ControlModule {
|
|
|
9198
9215
|
}
|
|
9199
9216
|
}
|
|
9200
9217
|
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
'small-radio': toDataUri(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><circle cx="36.93" cy="48.5" r="22" style="fill:none;stroke:red;stroke-miterlimit:10;stroke-width:4.535433070866142px"/><polyline points="42.56 25.87 53.06 9.51 54.06 27.5 65.07 10.37" style="fill:none;stroke:red;stroke-linejoin:bevel;stroke-width:4.535433070866142px"/><rect width="80" height="80" style="fill:red;opacity:0"/></g></g></svg>`),
|
|
9209
|
-
'large-radio': toDataUri(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><polygon points="39.96 28.87 51.18 48.3 62.4 67.73 39.96 67.73 17.53 67.73 28.75 48.3 39.96 28.87" style="fill:none;stroke:red;stroke-miterlimit:10;stroke-width:4.535433070866142px"/><polyline points="39.96 28.64 50.46 12.27 51.46 30.27 62.47 13.14" style="fill:none;stroke:red;stroke-linejoin:bevel;stroke-width:4.535433070866142px"/><rect width="80" height="80" style="fill:red;opacity:0"/></g></g></svg>`),
|
|
9218
|
+
/**
|
|
9219
|
+
* 军标内置默认图标。
|
|
9220
|
+
* SDK 内置常见军标类型的默认图标,业务层可通过 imgUrl / useDefaultIcon 参数覆盖或追加。
|
|
9221
|
+
*/
|
|
9222
|
+
const DEFAULT_SYMBOL_SVGS = {
|
|
9223
|
+
'small-radio': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><circle cx="36.93" cy="48.5" r="22" style="fill:none;stroke:red;stroke-miterlimit:10;stroke-width:4.535433070866142px"/><polyline points="42.56 25.87 53.06 9.51 54.06 27.5 65.07 10.37" style="fill:none;stroke:red;stroke-linejoin:bevel;stroke-width:4.535433070866142px"/><rect width="80" height="80" style="fill:red;opacity:0"/></g></g></svg>`,
|
|
9224
|
+
'large-radio': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><polygon points="39.96 28.87 51.18 48.3 62.4 67.73 39.96 67.73 17.53 67.73 28.75 48.3 39.96 28.87" style="fill:none;stroke:red;stroke-miterlimit:10;stroke-width:4.535433070866142px"/><polyline points="39.96 28.64 50.46 12.27 51.46 30.27 62.47 13.14" style="fill:none;stroke:red;stroke-linejoin:bevel;stroke-width:4.535433070866142px"/><rect width="80" height="80" style="fill:red;opacity:0"/></g></g></svg>`,
|
|
9210
9225
|
};
|
|
9211
9226
|
|
|
9227
|
+
/** Blob URL 缓存,避免重复创建 */
|
|
9228
|
+
const blobUrlCache = new Map();
|
|
9229
|
+
|
|
9230
|
+
/**
|
|
9231
|
+
* 获取内置军标图标的 Blob URL(比 data URI 更利于 Cesium 材质加载)
|
|
9232
|
+
* @param {string} type 军标类型
|
|
9233
|
+
* @returns {string | null}
|
|
9234
|
+
*/
|
|
9235
|
+
function getDefaultSymbolImage(type) {
|
|
9236
|
+
const svg = DEFAULT_SYMBOL_SVGS[type];
|
|
9237
|
+
if (!svg) return null;
|
|
9238
|
+
if (blobUrlCache.has(type)) return blobUrlCache.get(type);
|
|
9239
|
+
try {
|
|
9240
|
+
const blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });
|
|
9241
|
+
const url = URL.createObjectURL(blob);
|
|
9242
|
+
blobUrlCache.set(type, url);
|
|
9243
|
+
return url;
|
|
9244
|
+
} catch (e) {
|
|
9245
|
+
console.warn('生成军标图标 Blob URL 失败', e);
|
|
9246
|
+
return null;
|
|
9247
|
+
}
|
|
9248
|
+
}
|
|
9249
|
+
|
|
9212
9250
|
const Cesium$2 = getCesium();
|
|
9213
9251
|
|
|
9214
9252
|
/**
|
|
@@ -9227,10 +9265,21 @@ class MilitarySymbolModule {
|
|
|
9227
9265
|
this.eventModule = null;
|
|
9228
9266
|
|
|
9229
9267
|
this._editMode = false;
|
|
9268
|
+
this._editSymbolId = null;
|
|
9269
|
+
/** @type {Map<string, {move: Cesium.Entity, scale: Cesium.Entity, rotate: Cesium.Entity}>} */
|
|
9270
|
+
this._editHandles = new Map();
|
|
9230
9271
|
this._draggingId = null;
|
|
9272
|
+
this._draggingHandle = null;
|
|
9273
|
+
this._dragStartScreen = null;
|
|
9274
|
+
this._dragStartScale = 1;
|
|
9275
|
+
this._dragStartRotation = 0;
|
|
9276
|
+
this._dragStartDist = 0;
|
|
9277
|
+
this._dragStartAngle = 0;
|
|
9231
9278
|
this._dragObserverIds = [];
|
|
9232
9279
|
/** @type {Set<Function>} */
|
|
9233
9280
|
this._positionChangedCallbacks = new Set();
|
|
9281
|
+
/** @type {Set<Function>} */
|
|
9282
|
+
this._transformChangedCallbacks = new Set();
|
|
9234
9283
|
}
|
|
9235
9284
|
|
|
9236
9285
|
/**
|
|
@@ -9287,7 +9336,7 @@ class MilitarySymbolModule {
|
|
|
9287
9336
|
_resolveImage(id, options) {
|
|
9288
9337
|
const globalMode = this._defaultIconMode || this.config.militarySymbol?.defaultIconMode;
|
|
9289
9338
|
const mode = options.iconMode || globalMode || 'default';
|
|
9290
|
-
const defaultImage =
|
|
9339
|
+
const defaultImage = getDefaultSymbolImage(options.type);
|
|
9291
9340
|
const registeredImage = this.defaultImageMap.get(options.type);
|
|
9292
9341
|
const imgUrl = options.imgUrl || registeredImage || null;
|
|
9293
9342
|
|
|
@@ -9330,7 +9379,10 @@ class MilitarySymbolModule {
|
|
|
9330
9379
|
_loadImage(url) {
|
|
9331
9380
|
return new Promise((resolve, reject) => {
|
|
9332
9381
|
const img = new Image();
|
|
9333
|
-
|
|
9382
|
+
// data URI / blob URL 等同源资源不需要 crossOrigin;跨域 http 资源需要
|
|
9383
|
+
if (url && /^https?:\/\//.test(url)) {
|
|
9384
|
+
img.crossOrigin = 'anonymous';
|
|
9385
|
+
}
|
|
9334
9386
|
img.onload = () => resolve(img);
|
|
9335
9387
|
img.onerror = (e) => reject(e);
|
|
9336
9388
|
img.src = url;
|
|
@@ -9384,6 +9436,131 @@ class MilitarySymbolModule {
|
|
|
9384
9436
|
return this.symbolMap.has(id) ? id : null;
|
|
9385
9437
|
}
|
|
9386
9438
|
|
|
9439
|
+
/**
|
|
9440
|
+
* 根据鼠标拾取结果判断是否为编辑控制点
|
|
9441
|
+
* @private
|
|
9442
|
+
*/
|
|
9443
|
+
_getHandleType(pickedEntity) {
|
|
9444
|
+
if (!pickedEntity) return null;
|
|
9445
|
+
const id = typeof pickedEntity.id === 'string' ? pickedEntity.id : pickedEntity.id?.id;
|
|
9446
|
+
if (!id) return null;
|
|
9447
|
+
if (id.endsWith('_move')) return 'move';
|
|
9448
|
+
if (id.endsWith('_scale')) return 'scale';
|
|
9449
|
+
if (id.endsWith('_rotate')) return 'rotate';
|
|
9450
|
+
return null;
|
|
9451
|
+
}
|
|
9452
|
+
|
|
9453
|
+
/**
|
|
9454
|
+
* 计算编辑控制点的三维坐标
|
|
9455
|
+
* @private
|
|
9456
|
+
*/
|
|
9457
|
+
_getHandlePositions(position) {
|
|
9458
|
+
const center = Cesium$2.Cartesian3.fromDegrees(position[0], position[1], position[2] || 0);
|
|
9459
|
+
const matrix = Cesium$2.Transforms.eastNorthUpToFixedFrame(center);
|
|
9460
|
+
const offsetMeters = 120;
|
|
9461
|
+
const scaleOffset = Cesium$2.Matrix4.multiplyByPoint(
|
|
9462
|
+
matrix,
|
|
9463
|
+
new Cesium$2.Cartesian3(offsetMeters, 0, 0),
|
|
9464
|
+
new Cesium$2.Cartesian3()
|
|
9465
|
+
);
|
|
9466
|
+
const rotateOffset = Cesium$2.Matrix4.multiplyByPoint(
|
|
9467
|
+
matrix,
|
|
9468
|
+
new Cesium$2.Cartesian3(0, offsetMeters, 0),
|
|
9469
|
+
new Cesium$2.Cartesian3()
|
|
9470
|
+
);
|
|
9471
|
+
return { center, scale: scaleOffset, rotate: rotateOffset };
|
|
9472
|
+
}
|
|
9473
|
+
|
|
9474
|
+
/**
|
|
9475
|
+
* 为指定军标创建编辑控制点
|
|
9476
|
+
* @private
|
|
9477
|
+
*/
|
|
9478
|
+
_createEditHandles(symbolId) {
|
|
9479
|
+
this._removeEditHandles(symbolId);
|
|
9480
|
+
const symbol = this.symbolMap.get(symbolId);
|
|
9481
|
+
if (!symbol) return;
|
|
9482
|
+
|
|
9483
|
+
const positions = this._getHandlePositions(symbol.metadata.position);
|
|
9484
|
+
const commonPoint = {
|
|
9485
|
+
pixelSize: 14,
|
|
9486
|
+
outlineColor: Cesium$2.Color.WHITE,
|
|
9487
|
+
outlineWidth: 2,
|
|
9488
|
+
heightReference: Cesium$2.HeightReference.CLAMP_TO_GROUND,
|
|
9489
|
+
};
|
|
9490
|
+
const commonLabel = {
|
|
9491
|
+
font: '12px Microsoft YaHei',
|
|
9492
|
+
fillColor: Cesium$2.Color.WHITE,
|
|
9493
|
+
outlineColor: Cesium$2.Color.BLACK,
|
|
9494
|
+
outlineWidth: 2,
|
|
9495
|
+
style: Cesium$2.LabelStyle.FILL_AND_OUTLINE,
|
|
9496
|
+
verticalOrigin: Cesium$2.VerticalOrigin.BOTTOM,
|
|
9497
|
+
horizontalOrigin: Cesium$2.HorizontalOrigin.CENTER,
|
|
9498
|
+
pixelOffset: new Cesium$2.Cartesian2(0, -10),
|
|
9499
|
+
heightReference: Cesium$2.HeightReference.CLAMP_TO_GROUND,
|
|
9500
|
+
};
|
|
9501
|
+
|
|
9502
|
+
const handles = {};
|
|
9503
|
+
handles.move = this.viewer.entities.add({
|
|
9504
|
+
id: `${symbolId}_move`,
|
|
9505
|
+
position: positions.center,
|
|
9506
|
+
point: { ...commonPoint, color: Cesium$2.Color.LIME },
|
|
9507
|
+
label: { ...commonLabel, text: '移动' },
|
|
9508
|
+
});
|
|
9509
|
+
handles.scale = this.viewer.entities.add({
|
|
9510
|
+
id: `${symbolId}_scale`,
|
|
9511
|
+
position: positions.scale,
|
|
9512
|
+
point: { ...commonPoint, color: Cesium$2.Color.DEEPSKYBLUE },
|
|
9513
|
+
label: { ...commonLabel, text: '缩放' },
|
|
9514
|
+
});
|
|
9515
|
+
handles.rotate = this.viewer.entities.add({
|
|
9516
|
+
id: `${symbolId}_rotate`,
|
|
9517
|
+
position: positions.rotate,
|
|
9518
|
+
point: { ...commonPoint, color: Cesium$2.Color.RED },
|
|
9519
|
+
label: { ...commonLabel, text: '旋转' },
|
|
9520
|
+
});
|
|
9521
|
+
|
|
9522
|
+
this._editHandles.set(symbolId, handles);
|
|
9523
|
+
}
|
|
9524
|
+
|
|
9525
|
+
/**
|
|
9526
|
+
* 移除指定军标的编辑控制点
|
|
9527
|
+
* @private
|
|
9528
|
+
*/
|
|
9529
|
+
_removeEditHandles(symbolId) {
|
|
9530
|
+
const handles = this._editHandles.get(symbolId);
|
|
9531
|
+
if (!handles) return;
|
|
9532
|
+
Object.values(handles).forEach((entity) => {
|
|
9533
|
+
if (entity) this.viewer.entities.remove(entity);
|
|
9534
|
+
});
|
|
9535
|
+
this._editHandles.delete(symbolId);
|
|
9536
|
+
}
|
|
9537
|
+
|
|
9538
|
+
/**
|
|
9539
|
+
* 更新控制点位置以跟随军标
|
|
9540
|
+
* @private
|
|
9541
|
+
*/
|
|
9542
|
+
_updateHandlePositions(symbolId) {
|
|
9543
|
+
const symbol = this.symbolMap.get(symbolId);
|
|
9544
|
+
const handles = this._editHandles.get(symbolId);
|
|
9545
|
+
if (!symbol || !handles) return;
|
|
9546
|
+
const positions = this._getHandlePositions(symbol.metadata.position);
|
|
9547
|
+
handles.move.position = positions.center;
|
|
9548
|
+
handles.scale.position = positions.scale;
|
|
9549
|
+
handles.rotate.position = positions.rotate;
|
|
9550
|
+
}
|
|
9551
|
+
|
|
9552
|
+
/**
|
|
9553
|
+
* 将 WGS84 坐标转换为屏幕坐标
|
|
9554
|
+
* @private
|
|
9555
|
+
*/
|
|
9556
|
+
_cartesianToScreen(cartesian) {
|
|
9557
|
+
if (!cartesian) return null;
|
|
9558
|
+
try {
|
|
9559
|
+
return Cesium$2.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, cartesian);
|
|
9560
|
+
} catch (e) {
|
|
9561
|
+
return null;
|
|
9562
|
+
}
|
|
9563
|
+
}
|
|
9387
9564
|
/**
|
|
9388
9565
|
* 创建军标图元
|
|
9389
9566
|
* @param {string} id 军标唯一ID
|
|
@@ -9422,7 +9599,6 @@ class MilitarySymbolModule {
|
|
|
9422
9599
|
verticalOrigin: Cesium$2.VerticalOrigin.BOTTOM,
|
|
9423
9600
|
horizontalOrigin: Cesium$2.HorizontalOrigin.CENTER,
|
|
9424
9601
|
heightReference: Cesium$2.HeightReference.CLAMP_TO_GROUND,
|
|
9425
|
-
disableDepthTestDistance: 100000,
|
|
9426
9602
|
},
|
|
9427
9603
|
label: {
|
|
9428
9604
|
text: name,
|
|
@@ -9435,7 +9611,6 @@ class MilitarySymbolModule {
|
|
|
9435
9611
|
horizontalOrigin: Cesium$2.HorizontalOrigin.CENTER,
|
|
9436
9612
|
pixelOffset: new Cesium$2.Cartesian2(0, 4),
|
|
9437
9613
|
heightReference: Cesium$2.HeightReference.CLAMP_TO_GROUND,
|
|
9438
|
-
disableDepthTestDistance: 100000,
|
|
9439
9614
|
show: true,
|
|
9440
9615
|
},
|
|
9441
9616
|
show: visible,
|
|
@@ -9469,6 +9644,10 @@ class MilitarySymbolModule {
|
|
|
9469
9644
|
return false;
|
|
9470
9645
|
}
|
|
9471
9646
|
this.viewer.entities.remove(symbol.entity);
|
|
9647
|
+
this._removeEditHandles(id);
|
|
9648
|
+
if (this._editSymbolId === id) {
|
|
9649
|
+
this.disableEditMode();
|
|
9650
|
+
}
|
|
9472
9651
|
this.symbolMap.delete(id);
|
|
9473
9652
|
if (this._draggingId === id) {
|
|
9474
9653
|
this._draggingId = null;
|
|
@@ -9481,6 +9660,11 @@ class MilitarySymbolModule {
|
|
|
9481
9660
|
* 删除所有军标
|
|
9482
9661
|
*/
|
|
9483
9662
|
removeAll() {
|
|
9663
|
+
this._editHandles.forEach((_, id) => this._removeEditHandles(id));
|
|
9664
|
+
this._editHandles.clear();
|
|
9665
|
+
if (this._editMode) {
|
|
9666
|
+
this.disableEditMode();
|
|
9667
|
+
}
|
|
9484
9668
|
this.symbolMap.forEach((symbol) => {
|
|
9485
9669
|
this.viewer.entities.remove(symbol.entity);
|
|
9486
9670
|
});
|
|
@@ -9604,13 +9788,14 @@ class MilitarySymbolModule {
|
|
|
9604
9788
|
const pitch = options.pitch ?? -Cesium$2.Math.PI_OVER_TWO;
|
|
9605
9789
|
const range = options.range ?? 5000;
|
|
9606
9790
|
|
|
9607
|
-
return
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9791
|
+
return new Promise((resolve) => {
|
|
9792
|
+
this.viewer.camera.flyTo({
|
|
9793
|
+
destination: Cesium$2.Cartesian3.fromDegrees(position[0], position[1], (position[2] || 0) + range),
|
|
9794
|
+
orientation: { heading: 0, pitch, roll: 0 },
|
|
9795
|
+
duration,
|
|
9796
|
+
complete: () => resolve(true),
|
|
9797
|
+
cancel: () => resolve(false),
|
|
9798
|
+
});
|
|
9614
9799
|
});
|
|
9615
9800
|
}
|
|
9616
9801
|
|
|
@@ -9636,49 +9821,115 @@ class MilitarySymbolModule {
|
|
|
9636
9821
|
}
|
|
9637
9822
|
|
|
9638
9823
|
/**
|
|
9639
|
-
*
|
|
9640
|
-
*
|
|
9824
|
+
* 启用军标编辑模式(生成移动/缩放/旋转控制点)
|
|
9825
|
+
* @param {string} id 要编辑的军标ID
|
|
9641
9826
|
*/
|
|
9642
|
-
enableEditMode() {
|
|
9643
|
-
if (this._editMode)
|
|
9827
|
+
enableEditMode(id) {
|
|
9828
|
+
if (this._editMode) {
|
|
9829
|
+
if (this._editSymbolId === id) return;
|
|
9830
|
+
this.disableEditMode();
|
|
9831
|
+
}
|
|
9832
|
+
if (!this.symbolMap.has(id)) {
|
|
9833
|
+
console.warn(`军标 ${id} 不存在,无法启用编辑`);
|
|
9834
|
+
return;
|
|
9835
|
+
}
|
|
9644
9836
|
if (!this.eventModule) {
|
|
9645
|
-
console.warn('MilitarySymbolModule 未注入 EventModule
|
|
9837
|
+
console.warn('MilitarySymbolModule 未注入 EventModule,无法启用编辑');
|
|
9646
9838
|
return;
|
|
9647
9839
|
}
|
|
9648
9840
|
|
|
9649
9841
|
this._editMode = true;
|
|
9842
|
+
this._editSymbolId = id;
|
|
9843
|
+
this._createEditHandles(id);
|
|
9844
|
+
|
|
9845
|
+
const downId = this.eventModule.registerObserver('mouse:down', (lngLat, pickedEntity, movement) => {
|
|
9846
|
+
const handleType = this._getHandleType(pickedEntity);
|
|
9847
|
+
let symbolId = null;
|
|
9848
|
+
if (handleType) {
|
|
9849
|
+
symbolId = this._editSymbolId;
|
|
9850
|
+
} else {
|
|
9851
|
+
symbolId = this._getSymbolIdFromPick(pickedEntity);
|
|
9852
|
+
}
|
|
9853
|
+
if (!symbolId || symbolId !== this._editSymbolId) return;
|
|
9854
|
+
|
|
9855
|
+
const symbol = this.symbolMap.get(symbolId);
|
|
9856
|
+
const centerScreen = this._cartesianToScreen(symbol.entity.position.getValue(Cesium$2.JulianDate.now()));
|
|
9857
|
+
const mouseScreen = movement.position;
|
|
9858
|
+
if (centerScreen && mouseScreen) {
|
|
9859
|
+
const dx = mouseScreen.x - centerScreen.x;
|
|
9860
|
+
const dy = mouseScreen.y - centerScreen.y;
|
|
9861
|
+
this._dragStartDist = Math.hypot(dx, dy);
|
|
9862
|
+
this._dragStartAngle = Math.atan2(dx, -dy);
|
|
9863
|
+
} else {
|
|
9864
|
+
this._dragStartDist = 0;
|
|
9865
|
+
this._dragStartAngle = 0;
|
|
9866
|
+
}
|
|
9650
9867
|
|
|
9651
|
-
const downId = this.eventModule.registerObserver('mouse:down', (lngLat, pickedEntity) => {
|
|
9652
|
-
const symbolId = this._getSymbolIdFromPick(pickedEntity);
|
|
9653
|
-
if (!symbolId) return;
|
|
9654
9868
|
this._draggingId = symbolId;
|
|
9869
|
+
this._draggingHandle = handleType || 'move';
|
|
9870
|
+
this._dragStartScale = symbol.metadata.scale;
|
|
9871
|
+
this._dragStartRotation = symbol.metadata.rotation || 0;
|
|
9655
9872
|
this.viewer.scene.screenSpaceCameraController.enableInputs = false;
|
|
9656
9873
|
});
|
|
9657
9874
|
|
|
9658
9875
|
const moveId = this.eventModule.registerObserver('mouse:move', (lngLat, pickedEntity, movement) => {
|
|
9659
9876
|
if (!this._draggingId || !movement?.endPosition) return;
|
|
9660
9877
|
|
|
9661
|
-
const
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
carto.
|
|
9670
|
-
|
|
9671
|
-
|
|
9878
|
+
const symbol = this.symbolMap.get(this._draggingId);
|
|
9879
|
+
if (!symbol) return;
|
|
9880
|
+
|
|
9881
|
+
if (this._draggingHandle === 'move') {
|
|
9882
|
+
const cartesian = this.viewer.scene.pickPosition(movement.endPosition)
|
|
9883
|
+
|| this.viewer.scene.camera.pickEllipsoid(movement.endPosition, this.viewer.scene.globe.ellipsoid);
|
|
9884
|
+
if (!cartesian) return;
|
|
9885
|
+
|
|
9886
|
+
const carto = Cesium$2.Cartographic.fromCartesian(cartesian);
|
|
9887
|
+
const position = [
|
|
9888
|
+
Cesium$2.Math.toDegrees(carto.longitude),
|
|
9889
|
+
Cesium$2.Math.toDegrees(carto.latitude),
|
|
9890
|
+
carto.height,
|
|
9891
|
+
];
|
|
9892
|
+
this.update(this._draggingId, { position });
|
|
9893
|
+
this._updateHandlePositions(this._draggingId);
|
|
9894
|
+
} else if (this._draggingHandle === 'scale') {
|
|
9895
|
+
const centerScreen = this._cartesianToScreen(symbol.entity.position.getValue(Cesium$2.JulianDate.now()));
|
|
9896
|
+
if (!centerScreen) return;
|
|
9897
|
+
const dx = movement.endPosition.x - centerScreen.x;
|
|
9898
|
+
const dy = movement.endPosition.y - centerScreen.y;
|
|
9899
|
+
const dist = Math.hypot(dx, dy);
|
|
9900
|
+
const ratio = this._dragStartDist > 0 ? dist / this._dragStartDist : 1;
|
|
9901
|
+
const newScale = Math.max(0.1, this._dragStartScale * ratio);
|
|
9902
|
+
this.update(this._draggingId, { scale: newScale });
|
|
9903
|
+
} else if (this._draggingHandle === 'rotate') {
|
|
9904
|
+
const centerScreen = this._cartesianToScreen(symbol.entity.position.getValue(Cesium$2.JulianDate.now()));
|
|
9905
|
+
if (!centerScreen) return;
|
|
9906
|
+
const dx = movement.endPosition.x - centerScreen.x;
|
|
9907
|
+
const dy = movement.endPosition.y - centerScreen.y;
|
|
9908
|
+
const angle = Math.atan2(dx, -dy);
|
|
9909
|
+
const deltaDeg = Cesium$2.Math.toDegrees(angle - this._dragStartAngle);
|
|
9910
|
+
let newRotation = this._dragStartRotation + deltaDeg;
|
|
9911
|
+
newRotation = ((newRotation % 360) + 360) % 360;
|
|
9912
|
+
this.update(this._draggingId, { rotation: newRotation });
|
|
9913
|
+
}
|
|
9672
9914
|
});
|
|
9673
9915
|
|
|
9674
9916
|
const upId = this.eventModule.registerObserver('mouse:up', () => {
|
|
9675
9917
|
if (!this._draggingId) return;
|
|
9676
9918
|
const symbol = this.symbolMap.get(this._draggingId);
|
|
9677
|
-
const payload = symbol
|
|
9919
|
+
const payload = symbol
|
|
9920
|
+
? {
|
|
9921
|
+
id: this._draggingId,
|
|
9922
|
+
position: [...symbol.metadata.position],
|
|
9923
|
+
scale: symbol.metadata.scale,
|
|
9924
|
+
rotation: symbol.metadata.rotation,
|
|
9925
|
+
}
|
|
9926
|
+
: null;
|
|
9678
9927
|
this._draggingId = null;
|
|
9928
|
+
this._draggingHandle = null;
|
|
9679
9929
|
this.viewer.scene.screenSpaceCameraController.enableInputs = true;
|
|
9680
9930
|
if (payload) {
|
|
9681
|
-
this._positionChangedCallbacks.forEach((callback) => callback(payload));
|
|
9931
|
+
this._positionChangedCallbacks.forEach((callback) => callback({ id: payload.id, position: payload.position }));
|
|
9932
|
+
this._transformChangedCallbacks.forEach((callback) => callback(payload));
|
|
9682
9933
|
}
|
|
9683
9934
|
});
|
|
9684
9935
|
|
|
@@ -9686,13 +9937,12 @@ class MilitarySymbolModule {
|
|
|
9686
9937
|
}
|
|
9687
9938
|
|
|
9688
9939
|
/**
|
|
9689
|
-
*
|
|
9940
|
+
* 禁用军标编辑模式
|
|
9690
9941
|
*/
|
|
9691
9942
|
disableEditMode() {
|
|
9692
9943
|
if (!this._editMode) return;
|
|
9693
9944
|
if (this.eventModule) {
|
|
9694
9945
|
this._dragObserverIds.forEach((observerId) => {
|
|
9695
|
-
// 每个观察者注册时的事件类型固定,分别注销
|
|
9696
9946
|
['mouse:down', 'mouse:move', 'mouse:up'].forEach((eventType) => {
|
|
9697
9947
|
try {
|
|
9698
9948
|
this.eventModule.unregisterObserver(eventType, observerId);
|
|
@@ -9703,13 +9953,18 @@ class MilitarySymbolModule {
|
|
|
9703
9953
|
});
|
|
9704
9954
|
}
|
|
9705
9955
|
this._dragObserverIds = [];
|
|
9956
|
+
if (this._editSymbolId) {
|
|
9957
|
+
this._removeEditHandles(this._editSymbolId);
|
|
9958
|
+
}
|
|
9959
|
+
this._editSymbolId = null;
|
|
9706
9960
|
this._draggingId = null;
|
|
9961
|
+
this._draggingHandle = null;
|
|
9707
9962
|
this.viewer.scene.screenSpaceCameraController.enableInputs = true;
|
|
9708
9963
|
this._editMode = false;
|
|
9709
9964
|
}
|
|
9710
9965
|
|
|
9711
9966
|
/**
|
|
9712
|
-
*
|
|
9967
|
+
* 注册位置变化回调(仅位置)
|
|
9713
9968
|
* @param {Function} callback 回调参数 { id, position }
|
|
9714
9969
|
* @returns {Function} 注销函数
|
|
9715
9970
|
*/
|
|
@@ -9717,6 +9972,16 @@ class MilitarySymbolModule {
|
|
|
9717
9972
|
this._positionChangedCallbacks.add(callback);
|
|
9718
9973
|
return () => this._positionChangedCallbacks.delete(callback);
|
|
9719
9974
|
}
|
|
9975
|
+
|
|
9976
|
+
/**
|
|
9977
|
+
* 注册变换变化回调(位置、缩放、旋转)
|
|
9978
|
+
* @param {Function} callback 回调参数 { id, position, scale, rotation }
|
|
9979
|
+
* @returns {Function} 注销函数
|
|
9980
|
+
*/
|
|
9981
|
+
onTransformChanged(callback) {
|
|
9982
|
+
this._transformChangedCallbacks.add(callback);
|
|
9983
|
+
return () => this._transformChangedCallbacks.delete(callback);
|
|
9984
|
+
}
|
|
9720
9985
|
}
|
|
9721
9986
|
|
|
9722
9987
|
/**
|