tg-map-core 4.1.8 → 4.2.1

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.
@@ -1555,7 +1555,17 @@ class TalksEventTargetDelegate extends AbstractEventTargetDelegate {
1555
1555
  static EVENT_TYPE_MAP = typedRecord({
1556
1556
  'center-changed': 'movestart moving moveend zoomend',
1557
1557
  'zoom-changed': 'zoomend',
1558
+ // https://maptalks.org/maptalks.js/api/1.x/Map.html#event:setbaselayer
1559
+ 'map-type-changed': 'setbaselayer',
1558
1560
  });
1561
+ eventTypeMap;
1562
+ /**
1563
+ * @param eventTypeMap 额外的事件类型映射
1564
+ */
1565
+ constructor(inner, coordTypeSupplier, eventTypeMap) {
1566
+ super(inner, coordTypeSupplier);
1567
+ this.eventTypeMap = { ...TalksEventTargetDelegate.EVENT_TYPE_MAP, ...eventTypeMap };
1568
+ }
1559
1569
  addEventListener(type, listener) {
1560
1570
  const key = generateEventKey(type, listener);
1561
1571
  if (this.eventMap.has(key)) {
@@ -1573,14 +1583,14 @@ class TalksEventTargetDelegate extends AbstractEventTargetDelegate {
1573
1583
  }
1574
1584
  listener.call(this.target, ev);
1575
1585
  };
1576
- this.inner.on(TalksEventTargetDelegate.EVENT_TYPE_MAP[type] ?? type, actualListener);
1586
+ this.inner.on(this.eventTypeMap[type] ?? type, actualListener);
1577
1587
  this.eventMap.set(key, actualListener);
1578
1588
  }
1579
1589
  removeEventListener(type, listener) {
1580
1590
  const key = generateEventKey(type, listener);
1581
1591
  const actualListener = this.eventMap.get(key);
1582
1592
  if (actualListener) {
1583
- this.inner.off(TalksEventTargetDelegate.EVENT_TYPE_MAP[type] ?? type, actualListener);
1593
+ this.inner.off(this.eventTypeMap[type] ?? type, actualListener);
1584
1594
  this.eventMap.delete(key);
1585
1595
  }
1586
1596
  else {
@@ -1751,6 +1761,19 @@ function hideBaiduMapUnauthWarn() {
1751
1761
  }
1752
1762
  return false;
1753
1763
  };
1764
+ if (!isBaiduGL()) {
1765
+ // 新的V3版也会直接从签名的`B_BUSINESS_INFO`中检测是否弹窗警告, 强制清空它可以规避检测(
1766
+ Object.defineProperty(window, 'B_BUSINESS_INFO', {
1767
+ configurable: true,
1768
+ enumerable: true,
1769
+ get: () => {
1770
+ return undefined;
1771
+ },
1772
+ set: (v) => {
1773
+ console.debug('B_BUSINESS_INFO', 'set', v);
1774
+ },
1775
+ });
1776
+ }
1754
1777
  let originalBMap;
1755
1778
  let originalBMapVerifyCbk;
1756
1779
  Object.defineProperty(window, 'BMap', {
@@ -2187,13 +2210,17 @@ exports.BuildInMapTypeId = void 0;
2187
2210
  })(exports.BuildInMapTypeId || (exports.BuildInMapTypeId = {}));
2188
2211
  class BuildInMapType {
2189
2212
  id;
2213
+ index;
2190
2214
  baidu;
2191
2215
  google;
2192
2216
  googleCoordType;
2193
- constructor(id, baidu, // 需要延迟初始化, 故写成方法
2217
+ constructor(id,
2218
+ /** 在{@link MapType.BUILD_IN_MAP_TYPES.values}中的index */
2219
+ index, baidu, // 需要延迟初始化, 故写成方法
2194
2220
  google, // 同上
2195
2221
  googleCoordType) {
2196
2222
  this.id = id;
2223
+ this.index = index;
2197
2224
  this.baidu = baidu;
2198
2225
  this.google = google;
2199
2226
  this.googleCoordType = googleCoordType;
@@ -2303,10 +2330,10 @@ class TrafficLayer {
2303
2330
  }
2304
2331
  exports.MapType = void 0;
2305
2332
  (function (MapType) {
2306
- MapType.NORMAL = new BuildInMapType(exports.BuildInMapTypeId.normal, () => BMAP_NORMAL_MAP, () => google.maps.MapTypeId.ROADMAP, exports.CoordType.gcj02);
2307
- MapType.SATELLITE = new BuildInMapType(exports.BuildInMapTypeId.satellite, () => BMAP_SATELLITE_MAP, () => google.maps.MapTypeId.SATELLITE, exports.CoordType.wgs84);
2308
- MapType.HYBRID = new BuildInMapType(exports.BuildInMapTypeId.hybrid, () => BMAP_HYBRID_MAP, () => google.maps.MapTypeId.HYBRID, exports.CoordType.gcj02);
2309
- MapType.TERRAIN = new BuildInMapType('terrain', () => /* 三维 */ BMAP_PERSPECTIVE_MAP, () => /* 地形 */ google.maps.MapTypeId.TERRAIN, exports.CoordType.wgs84);
2333
+ MapType.NORMAL = new BuildInMapType(exports.BuildInMapTypeId.normal, 0, () => BMAP_NORMAL_MAP, () => google.maps.MapTypeId.ROADMAP, exports.CoordType.gcj02);
2334
+ MapType.SATELLITE = new BuildInMapType(exports.BuildInMapTypeId.satellite, 1, () => BMAP_SATELLITE_MAP, () => google.maps.MapTypeId.SATELLITE, exports.CoordType.wgs84);
2335
+ MapType.HYBRID = new BuildInMapType(exports.BuildInMapTypeId.hybrid, 2, () => BMAP_HYBRID_MAP, () => google.maps.MapTypeId.HYBRID, exports.CoordType.gcj02);
2336
+ MapType.TERRAIN = new BuildInMapType('terrain', 3, () => /* 三维 */ BMAP_PERSPECTIVE_MAP, () => /* 地形 */ google.maps.MapTypeId.TERRAIN, exports.CoordType.wgs84);
2310
2337
  MapType.BUILD_IN_MAP_TYPES = new FastFindValues([MapType.NORMAL, MapType.SATELLITE, MapType.HYBRID, MapType.TERRAIN]);
2311
2338
  })(exports.MapType || (exports.MapType = {}));
2312
2339
 
@@ -2319,6 +2346,10 @@ exports.MapTypeControlType = void 0;
2319
2346
  const MAP_TYPES_DEFAULT = [exports.MapType.NORMAL, exports.MapType.SATELLITE, exports.MapType.HYBRID];
2320
2347
  class BaiduMapTypeControl extends BaiduControl {
2321
2348
  static create(options) {
2349
+ if (isBaiduGL()) {
2350
+ // GL版, 不存在MapTypeControl...故返回空
2351
+ return new EmptyControl(true, options.position ?? exports.ControlPosition.TOP_LEFT);
2352
+ }
2322
2353
  const mapTypes = options.mapTypes ?? MAP_TYPES_DEFAULT;
2323
2354
  const type2baidu = {
2324
2355
  [exports.MapTypeControlType.DEFAULT]: BMAP_MAPTYPE_CONTROL_HORIZONTAL,
@@ -2370,9 +2401,13 @@ class GoogleMapTypeControl extends GoogleControl {
2370
2401
  });
2371
2402
  }
2372
2403
  }
2373
- class TalksMapTypeControl extends EmptyControl {
2404
+ class TalksMapTypeControl extends TalksControl {
2374
2405
  static create(options) {
2375
- return new TalksMapTypeControl(true, options.position ?? exports.ControlPosition.TOP_LEFT);
2406
+ const position = options.position ?? exports.ControlPosition.TOP_LEFT;
2407
+ const inner = new maptalks__namespace.control.LayerSwitcher({
2408
+ position: exports.ControlPositionConverter.getTalks().toValue(position),
2409
+ });
2410
+ return new TalksMapTypeControl(inner, position);
2376
2411
  }
2377
2412
  }
2378
2413
 
@@ -7320,7 +7355,7 @@ class TalksMarkerClusterer {
7320
7355
  this.inner = new maptalks_markercluster.ClusterLayer('cluster', options.markers?.map(it => it.innerOverlay), exports.Objects.deleteUndefinedPropertyOnPlainObjectDeeply({
7321
7356
  ...ClusterIconStyle.toTalks(options.styles),
7322
7357
  // {@macro marker_clusterer_grid_size}
7323
- maxClusterRadius: options.gridSize ?? (map.currentBaseLayerId === 'baidu' || map.currentBaseLayerId === 'baidu-detail' ? 60 : 100),
7358
+ maxClusterRadius: options.gridSize ?? (map.cachedBaseLayerId === 'baidu' || map.cachedBaseLayerId === 'baidu-detail' ? 60 : 100),
7324
7359
  maxClusterZoom: options.maxZoom,
7325
7360
  zIndex: options.zIndex,
7326
7361
  }));
@@ -7656,6 +7691,12 @@ class BaseMap {
7656
7691
  removeOverlayMapType(mapType) {
7657
7692
  this.removeLayer(mapType);
7658
7693
  }
7694
+ addOverlay(overlay) {
7695
+ overlay.addTo(this);
7696
+ }
7697
+ removeOverlay(overlay) {
7698
+ overlay.remove();
7699
+ }
7659
7700
  addControl(control) {
7660
7701
  control.addTo(this);
7661
7702
  }
@@ -7692,9 +7733,6 @@ class Overlay {
7692
7733
  removeEventListener(type, listener) {
7693
7734
  this.delegate.removeEventListener(type, listener);
7694
7735
  }
7695
- remove() {
7696
- this.map.removeOverlay(this);
7697
- }
7698
7736
  }
7699
7737
  class GoogleOverlay extends Overlay {
7700
7738
  map;
@@ -7705,6 +7743,13 @@ class GoogleOverlay extends Overlay {
7705
7743
  createDelegate() {
7706
7744
  return new GoogleEventTargetDelegate(this.innerOverlay, this.map);
7707
7745
  }
7746
+ addTo(map) {
7747
+ this.map = map;
7748
+ this.innerOverlay.setMap(map.innerMap);
7749
+ }
7750
+ remove() {
7751
+ this.innerOverlay.setMap(null);
7752
+ }
7708
7753
  isVisible() {
7709
7754
  return this.innerOverlay.getVisible();
7710
7755
  }
@@ -7721,6 +7766,13 @@ class BaiduOverlay extends Overlay {
7721
7766
  createDelegate() {
7722
7767
  return new BaiduEventTargetDelegate(this.innerOverlay, this.map);
7723
7768
  }
7769
+ addTo(map) {
7770
+ this.map = map;
7771
+ this.map.innerMap.addOverlay(this.innerOverlay);
7772
+ }
7773
+ remove() {
7774
+ this.map.innerMap.removeOverlay(this.innerOverlay);
7775
+ }
7724
7776
  /** 仅限内部使用; 设为private时, 生成的d.ts文件中, 方法返回值会变成any, 故改成了public */
7725
7777
  get overlay() {
7726
7778
  // 这几个属性被声明成可选的, 这里将其强转成必选
@@ -7830,11 +7882,43 @@ class GoogleShape extends GoogleOverlay {
7830
7882
  }
7831
7883
  }
7832
7884
  class TalksShape extends TalksOverlay {
7885
+ addTo(map) {
7886
+ this.map = map;
7887
+ this.map.overlayLayer.addGeometry(this.innerOverlay);
7888
+ // 添加到地图中之后, startEdit()才有效
7889
+ if (this.isEditable() && !this.innerOverlay.isEditing()) {
7890
+ this.innerOverlay.startEdit();
7891
+ }
7892
+ }
7893
+ remove() {
7894
+ this.map.overlayLayer.removeGeometry(this.innerOverlay);
7895
+ }
7896
+ /**
7897
+ * ## 编辑状态的映射
7898
+ * tg-map的editable, 直接表示是否处于编辑状态
7899
+ * talks的editable, 只是标记overlay是否可以编辑(默认为true), 要进入编辑状态(isEditing), 还需要执行startEdit()
7900
+ * 也就是说我们需要想办法把talks的四个状态, 映射为tg-map的两个状态
7901
+ *
7902
+ * 我们的做法是, 用editable保存isEditing期望的值, 保证editable为true时isEditing也会为true, 为false时isEditing也会为false
7903
+ * 这样就可以和tg-map的editable的语义简单对应上了
7904
+ *
7905
+ * @see addTo
7906
+ * @see setEditable
7907
+ */
7833
7908
  isEditable() {
7834
- return this.innerOverlay.config().editable ?? true;
7909
+ return this.innerOverlay.options.editable ?? false;
7835
7910
  }
7836
7911
  setEditable(editable) {
7912
+ // 同步设置editable和isEditing
7913
+ // TODO: 2026/01/23 ipcjs 切换编辑状态时, 控制台会报重复注册事件警告, 已提PR: https://github.com/maptalks/maptalks.js/pull/2796
7837
7914
  this.innerOverlay.config({ editable: editable });
7915
+ const isEditing = this.innerOverlay.isEditing();
7916
+ if (editable) {
7917
+ !isEditing && this.innerOverlay.startEdit();
7918
+ }
7919
+ else {
7920
+ isEditing && this.innerOverlay.endEdit();
7921
+ }
7838
7922
  }
7839
7923
  setStrokeColor(color) {
7840
7924
  this.innerOverlay.updateSymbol({ lineColor: color });
@@ -8004,6 +8088,41 @@ class TalksCircle extends TalksShape {
8004
8088
  });
8005
8089
  return new TalksCircle(inner, coord, this);
8006
8090
  }
8091
+ prevCenter;
8092
+ prevRadius;
8093
+ eventHubDelegate;
8094
+ createDelegate() {
8095
+ return (this.eventHubDelegate = new EventHubEventTargetDelegate(super.createDelegate(), {
8096
+ types: ['radius-changed', 'center-changed'],
8097
+ onListen: (type) => {
8098
+ if (type === 'radius-changed') {
8099
+ this.prevRadius = this.innerOverlay.getRadius();
8100
+ this.innerOverlay.on('editrecord', this.onRadiusChanged);
8101
+ }
8102
+ else {
8103
+ this.prevCenter = this.innerOverlay.getCoordinates();
8104
+ this.innerOverlay.on('editrecord', this.onCenterChanged);
8105
+ }
8106
+ },
8107
+ onCancel: (type) => {
8108
+ this.innerOverlay.off('editrecord', type === 'radius-changed' ? this.onRadiusChanged : this.onCenterChanged);
8109
+ },
8110
+ }));
8111
+ }
8112
+ onRadiusChanged = () => {
8113
+ const radius = this.innerOverlay.getRadius();
8114
+ if (this.prevRadius !== radius) {
8115
+ this.eventHubDelegate?.notify({ type: 'radius-changed', target: this });
8116
+ this.prevRadius = radius;
8117
+ }
8118
+ };
8119
+ onCenterChanged = () => {
8120
+ const center = this.innerOverlay.getCoordinates();
8121
+ if (this.prevCenter !== center && !this.prevCenter?.equals(center)) {
8122
+ this.eventHubDelegate?.notify({ type: 'center-changed', target: this });
8123
+ this.prevCenter = center;
8124
+ }
8125
+ };
8007
8126
  setCenter(center) {
8008
8127
  this.coordType = this.map.coordType;
8009
8128
  this.innerOverlay.setCoordinates(center.toTalks(this.coordType));
@@ -9148,6 +9267,13 @@ class TalksLabelOverlay extends TalksOverlay {
9148
9267
  });
9149
9268
  return new TalksLabelOverlay(label, coord, this);
9150
9269
  }
9270
+ addTo(map) {
9271
+ this.map = map;
9272
+ this.innerOverlay.addTo(map.innerMap);
9273
+ }
9274
+ remove() {
9275
+ this.innerOverlay.remove();
9276
+ }
9151
9277
  setContent(content) {
9152
9278
  this.innerOverlay.setContent(content);
9153
9279
  }
@@ -9159,7 +9285,7 @@ class TalksLabelOverlay extends TalksOverlay {
9159
9285
  this.innerOverlay.setCoordinates(position.toTalks(this.coordType));
9160
9286
  }
9161
9287
  getOffset() {
9162
- const options = this.innerOverlay.config();
9288
+ const options = this.innerOverlay.options;
9163
9289
  return { x: options.dx ?? 0, y: options.dy ?? 0 };
9164
9290
  }
9165
9291
  setOffset(offset) {
@@ -9666,6 +9792,13 @@ class TalksMarker extends TalksOverlay {
9666
9792
  super(innerOverlay, coordType, map);
9667
9793
  this.state = state;
9668
9794
  }
9795
+ addTo(map) {
9796
+ this.map = map;
9797
+ this.map.markerLayer.addGeometry(this.innerOverlay);
9798
+ }
9799
+ remove() {
9800
+ this.map.markerLayer.removeGeometry(this.innerOverlay);
9801
+ }
9669
9802
  getPosition() {
9670
9803
  return LatLng.fromTalks(this.innerOverlay.getCoordinates(), this.coordType);
9671
9804
  }
@@ -9700,13 +9833,13 @@ class TalksMarker extends TalksOverlay {
9700
9833
  this.innerOverlay.config('interactive', enable);
9701
9834
  }
9702
9835
  isClickable() {
9703
- return this.innerOverlay.config().interactive ?? true;
9836
+ return this.innerOverlay.options.interactive ?? true;
9704
9837
  }
9705
9838
  setDraggable(enable) {
9706
9839
  this.innerOverlay.config('draggable', enable);
9707
9840
  }
9708
9841
  isDraggable() {
9709
- return this.innerOverlay.config().draggable ?? false;
9842
+ return this.innerOverlay.options.draggable ?? false;
9710
9843
  }
9711
9844
  setZIndex(zIndex) {
9712
9845
  this.innerOverlay.setZIndex(zIndex ?? 0);
@@ -9934,6 +10067,12 @@ class TalksPolyline extends TalksShape {
9934
10067
  });
9935
10068
  return new TalksPolyline(inner, coordType, this);
9936
10069
  }
10070
+ createDelegate() {
10071
+ return new TalksEventTargetDelegate(this.innerOverlay, this.map, {
10072
+ // https://maptalks.org/maptalks.js/api/1.x/Geometry.html#event:editrecord
10073
+ 'path-edited': 'editrecord',
10074
+ });
10075
+ }
9937
10076
  getPath() {
9938
10077
  return this.innerOverlay.getCoordinates().map(it => LatLng.fromTalks(it, this.coordType));
9939
10078
  }
@@ -10052,6 +10191,12 @@ class TalksPolygon extends TalksShape {
10052
10191
  });
10053
10192
  return new TalksPolygon(inner, coord, this);
10054
10193
  }
10194
+ createDelegate() {
10195
+ return new TalksEventTargetDelegate(this.innerOverlay, this.map, {
10196
+ // https://maptalks.org/maptalks.js/api/1.x/Geometry.html#event:editrecord
10197
+ 'paths-edited': 'editrecord',
10198
+ });
10199
+ }
10055
10200
  getPaths() {
10056
10201
  return this.innerOverlay.getCoordinates()
10057
10202
  .map(path => path.map(it => LatLng.fromTalks(it, this.coordType)));
@@ -10217,6 +10362,12 @@ class TalksRectangle extends TalksShape {
10217
10362
  height: computeDistanceBetween(nw, bounds.sw),
10218
10363
  };
10219
10364
  }
10365
+ createDelegate() {
10366
+ return new TalksEventTargetDelegate(this.innerOverlay, this.map, {
10367
+ // https://maptalks.org/maptalks.js/api/1.x/Geometry.html#event:editrecord
10368
+ 'bounds-changed': 'editrecord',
10369
+ });
10370
+ }
10220
10371
  getBounds() {
10221
10372
  return LatLngBounds.fromTalks(this.innerOverlay.getExtent(), this.coordType);
10222
10373
  }
@@ -10419,12 +10570,6 @@ class BaiduMap extends BaseMap {
10419
10570
  removeElementOverlay(overlay) {
10420
10571
  this.map.removeOverlay(overlay.asBaidu());
10421
10572
  }
10422
- addOverlay(overlay) {
10423
- this.map.addOverlay(overlay.innerOverlay);
10424
- }
10425
- removeOverlay(overlay) {
10426
- this.map.removeOverlay(overlay.innerOverlay);
10427
- }
10428
10573
  addCustomControl(control) {
10429
10574
  if (!control.inner) {
10430
10575
  const BaiduControl = class extends BMap.Control {
@@ -10645,12 +10790,6 @@ class GoogleMap extends BaseMap {
10645
10790
  removeElementOverlay(overlay) {
10646
10791
  overlay.asGoogle().setMap(null);
10647
10792
  }
10648
- addOverlay(overlay) {
10649
- overlay.innerOverlay.setMap(this.map);
10650
- }
10651
- removeOverlay(overlay) {
10652
- overlay.innerOverlay.setMap(null);
10653
- }
10654
10793
  addCustomControl(control) {
10655
10794
  if (!control.inner) {
10656
10795
  control.inner = control.onCreateElement();
@@ -10799,12 +10938,6 @@ class HereMap extends BaseMap {
10799
10938
  removeElementOverlay(overlay) {
10800
10939
  throw new Error('Method not implemented.');
10801
10940
  }
10802
- addOverlay(overlay) {
10803
- throw new Error('Method not implemented.');
10804
- }
10805
- removeOverlay(overlay) {
10806
- throw new Error('Method not implemented.');
10807
- }
10808
10941
  createMarker(options) {
10809
10942
  throw new Error('Method not implemented.');
10810
10943
  }
@@ -10886,11 +11019,14 @@ const quadKey = (z, x, y) => {
10886
11019
  };
10887
11020
  const talksBaseLayerIds = [
10888
11021
  'osm',
10889
- 'osm-simple',
11022
+ 'osm-light',
11023
+ 'osm-dark',
11024
+ 'osm-terrain',
10890
11025
  'google',
10891
11026
  'baidu',
10892
11027
  'baidu-detail',
10893
11028
  'amap',
11029
+ 'amap-terrain',
10894
11030
  'tencent',
10895
11031
  'geoq',
10896
11032
  'tianditu',
@@ -10902,7 +11038,8 @@ function talksBaseLayerIdToCoordType(layerId) {
10902
11038
  case 'baidu':
10903
11039
  case 'baidu-detail':
10904
11040
  return exports.CoordType.bd09;
10905
- case 'osm-simple':
11041
+ case 'osm-light':
11042
+ case 'osm-dark':
10906
11043
  case 'osm':
10907
11044
  case 'yandex':
10908
11045
  return exports.CoordType.wgs84;
@@ -10923,15 +11060,29 @@ function talksBaseLayerIdToCoordType(layerId) {
10923
11060
  * @see https://maptalks.org/examples/cn/tilelayer-projection/baidu/#tilelayer-projection_baidu
10924
11061
  */
10925
11062
  const TILE_LAYER_BAIDU_SCALER = 1;
10926
- function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
11063
+ function createTalksBaseLayerImpl(layerId, { id = layerId, visible = true, } = {}) {
10927
11064
  switch (layerId) {
10928
11065
  case 'amap':
10929
11066
  return new maptalks__namespace.TileLayer(id, {
10930
11067
  visible,
10931
- urlTemplate: 'http://webrd03.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}&lang=zh_cn',
11068
+ urlTemplate: 'http://webrd{s}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}&lang=zh_cn',
11069
+ subdomains: ['01', '02', '03', '04'],
10932
11070
  minZoom: 3,
10933
11071
  maxZoom: 18,
10934
11072
  attribution: '&copy; <a target="_blank" href="https://amap.com/">AMap</a>',
11073
+ spatialReference: { projection: 'EPSG:3857' },
11074
+ });
11075
+ case 'amap-terrain':
11076
+ // http://examples.maptalks.com/examples/cn/3d/terrain/load
11077
+ return new maptalks__namespace.TileLayer(id, {
11078
+ visible,
11079
+ minZoom: 1,
11080
+ // 深圳最大可以到18级, 一些偏远地带, 18级可能没有数据
11081
+ maxZoom: 18,
11082
+ urlTemplate: 'http://webst{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
11083
+ subdomains: ['01', '02', '03', '04'],
11084
+ attribution: '&copy; <a target="_blank" href="https://amap.com/">AMap</a>',
11085
+ spatialReference: { projection: 'EPSG:3857' },
10935
11086
  });
10936
11087
  case 'baidu':
10937
11088
  return new maptalks__namespace.TileLayer(id, {
@@ -10939,20 +11090,20 @@ function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
10939
11090
  urlTemplate: `http://online{s}.map.bdimg.com/tile/?qt=vtile&x={x}&y={y}&z={z}&styles=pl&type=sate&scaler=${TILE_LAYER_BAIDU_SCALER}`,
10940
11091
  subdomains: ['0', '1', '2', '3'],
10941
11092
  spatialReference: {
10942
- projection: 'baidu',
11093
+ projection: 'BAIDU',
10943
11094
  },
10944
11095
  minZoom: 3,
10945
11096
  maxZoom: 20,
10946
11097
  attribution: '&copy; <a target="_blank" href="http://map.baidu.com">Baidu</a>',
10947
11098
  });
10948
11099
  case 'baidu-detail':
10949
- // 参考: https://maptalks.org/examples/cn/tilelayer-projection/baidu/#tilelayer-projection_baidu
11100
+ // https://maptalks.org/examples/cn/tilelayer-projection/baidu/#tilelayer-projection_baidu
10950
11101
  return new maptalks__namespace.TileLayer(id, {
10951
11102
  visible,
10952
11103
  urlTemplate: `https://gss{s}.bdstatic.com/8bo_dTSlRsgBo1vgoIiO_jowehsv/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=${TILE_LAYER_BAIDU_SCALER}&udt=20170927`,
10953
11104
  subdomains: ['0', '1', '2', '3'],
10954
11105
  spatialReference: {
10955
- projection: 'baidu',
11106
+ projection: 'BAIDU',
10956
11107
  },
10957
11108
  minZoom: 3,
10958
11109
  maxZoom: 19,
@@ -10967,6 +11118,7 @@ function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
10967
11118
  subdomains: ['0', '1', '2', '3'],
10968
11119
  minZoom: 3,
10969
11120
  maxZoom: 18,
11121
+ spatialReference: { projection: 'EPSG:3857' },
10970
11122
  });
10971
11123
  case 'google':
10972
11124
  return new maptalks__namespace.TileLayer(id, {
@@ -10974,6 +11126,7 @@ function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
10974
11126
  urlTemplate: 'https://api.xiox.top/proxy/https://maps.google.com/maps/vt?lyrs=m&x={x}&y={y}&z={z}&hl=zh-CN',
10975
11127
  subdomains: ['0', '1', '2', '3'],
10976
11128
  attribution: '&copy; <a target="_blank" href="https://www.google.com/maps">Google</a>',
11129
+ spatialReference: { projection: 'EPSG:3857' },
10977
11130
  });
10978
11131
  case 'geoq':
10979
11132
  // 不知道是哪家的, 无法显示
@@ -10981,6 +11134,7 @@ function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
10981
11134
  visible,
10982
11135
  urlTemplate: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}',
10983
11136
  subdomains: ['0', '1', '2', '3'],
11137
+ spatialReference: { projection: 'EPSG:3857' },
10984
11138
  });
10985
11139
  case 'tianditu':
10986
11140
  // key已失效, 无法显示
@@ -11003,6 +11157,7 @@ function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
11003
11157
  subdomains: ['1', '2', '3', '4'],
11004
11158
  maxZoom: 21,
11005
11159
  attribution: '&copy; <a target="_blank" href="https://yandex.com/maps/">Yandex</a>',
11160
+ spatialReference: { projection: 'EPSG:3857' },
11006
11161
  });
11007
11162
  case 'bing':
11008
11163
  return new maptalks__namespace.TileLayer(id, {
@@ -11011,49 +11166,97 @@ function createTalksBaseLayer(layerId, { id = layerId, visible = true, } = {}) {
11011
11166
  subdomains: ['1', '2', '3'],
11012
11167
  minZoom: 3,
11013
11168
  maxZoom: 18,
11169
+ spatialReference: { projection: 'EPSG:3857' },
11014
11170
  });
11015
11171
  case 'osm':
11172
+ // https://operations.osmfoundation.org/policies/tiles/
11016
11173
  return new maptalks__namespace.TileLayer(id, {
11017
11174
  visible,
11018
11175
  urlTemplate: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
11019
11176
  subdomains: ['a', 'b', 'c'],
11020
11177
  attribution: '&copy; <a target="_blank" href="http://www.osm.org/copyright">OSM</a>',
11178
+ spatialReference: { projection: 'EPSG:3857' },
11021
11179
  });
11022
- case 'osm-simple':
11180
+ case 'osm-light':
11181
+ // https://github.com/CartoDB/basemap-styles
11023
11182
  return new maptalks__namespace.TileLayer(id, {
11024
11183
  visible,
11025
11184
  urlTemplate: 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
11026
11185
  subdomains: ['a', 'b', 'c', 'd'],
11027
11186
  attribution: '&copy; <a target="_blank" href="http://www.osm.org/copyright">OSM</a> contributors, &copy; <a target="_blank" href="https://carto.com/attributions">CARTO</a>',
11187
+ spatialReference: { projection: 'EPSG:3857' },
11188
+ });
11189
+ case 'osm-dark':
11190
+ // https://github.com/CartoDB/basemap-styles
11191
+ return new maptalks__namespace.TileLayer(id, {
11192
+ visible,
11193
+ urlTemplate: 'http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',
11194
+ subdomains: ['a', 'b', 'c', 'd'],
11195
+ attribution: '&copy; <a target="_blank" href="http://www.osm.org/copyright">OSM</a> contributors, &copy; <a target="_blank" href="https://carto.com/attributions">CARTO</a>',
11196
+ spatialReference: { projection: 'EPSG:3857' },
11197
+ });
11198
+ case 'osm-terrain':
11199
+ // https://wiki.openstreetmap.org/wiki/OpenTopoMap#Usage
11200
+ return new maptalks__namespace.TileLayer(id, {
11201
+ visible,
11202
+ urlTemplate: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
11203
+ subdomains: ['a', 'b', 'c'],
11204
+ attribution: '&copy; <a target="_blank" href="http://www.osm.org/copyright">OSM</a>',
11205
+ spatialReference: { projection: 'EPSG:3857' },
11028
11206
  });
11029
11207
  }
11030
11208
  }
11209
+ const createTalksBaseLayer = process.env.NODE_ENV !== 'production'
11210
+ ? (layerId, options) => {
11211
+ const layer = createTalksBaseLayerImpl(layerId, options);
11212
+ if (layer.options.visible == null || layer.options.spatialReference == null) {
11213
+ console.warn('创建的baseLayer必须设置visible和spatialReference', layer.options);
11214
+ }
11215
+ return layer;
11216
+ }
11217
+ : createTalksBaseLayerImpl;
11031
11218
 
11032
11219
  const MAP_ATTRIBUTION_TG = { content: 'TG' };
11033
11220
  class TalksMap extends BaseMap {
11034
11221
  mapOptions;
11222
+ baseLayoutIds;
11035
11223
  map;
11224
+ attributionControl;
11225
+ baseLayerGroup;
11226
+ mapStyleTheme;
11227
+ /**
11228
+ * 由于通过{@link MapTypeControl}, maptalks可以在内部切换可见的baseLayer, 所以要获取实际当前的显示的baseLayer, 应该使用{@link getCurrentBaseLayer}
11229
+ * 但为了方便快速的执行{@link coordType}, 因而增加了这个缓存的值
11230
+ * @internal
11231
+ * */
11232
+ cachedBaseLayerId;
11036
11233
  /** @internal */
11037
- currentBaseLayerId;
11038
11234
  markerLayer;
11235
+ /** @internal */
11039
11236
  overlayLayer;
11040
- constructor(element, mapOptions, baseLayoutIds) {
11237
+ constructor(element, mapOptions,
11238
+ /**
11239
+ * 最多8项, 前四项对应{@link MapType.BUILD_IN_MAP_TYPES}的四个值(普通、卫星、混合、地形)的亮色版, 后四项对应暗色版
11240
+ * @see computeBaseLayerId
11241
+ */
11242
+ baseLayoutIds) {
11041
11243
  super(element);
11042
11244
  this.mapOptions = mapOptions;
11043
- // TODO: 2025/11/05 ipcjs 实现MapType机制
11044
- const buildInMapTypeIdIndex = tgCommons.StringEnums.values(exports.BuildInMapTypeId).indexOf(mapOptions.buildInMapTypeId ?? exports.BuildInMapTypeId.normal);
11045
- this.currentBaseLayerId = baseLayoutIds[buildInMapTypeIdIndex] ?? baseLayoutIds[0];
11046
- const baseLayers = baseLayoutIds.map(id => createTalksBaseLayer(id, { visible: id === this.currentBaseLayerId }));
11047
- const baseLayer = baseLayers.find(it => it.isVisible());
11245
+ this.baseLayoutIds = baseLayoutIds;
11246
+ this.mapStyleTheme = mapOptions.mapStyle?.talks?.theme ?? 'light';
11247
+ this.cachedBaseLayerId = this.computeBaseLayerId(mapOptions.buildInMapTypeId, this.mapStyleTheme);
11248
+ this.baseLayerGroup = new maptalks__namespace.GroupTileLayer('base', baseLayoutIds
11249
+ .filter(tgCommons.isTruthy)
11250
+ .map(id => createTalksBaseLayer(id, { visible: id === this.cachedBaseLayerId })));
11048
11251
  this.markerLayer = new maptalks__namespace.VectorLayer('markers');
11049
11252
  this.overlayLayer = new maptalks__namespace.VectorLayer('overlays');
11253
+ const baseLayer = this.getCurrentBaseLayer();
11050
11254
  this.map = new maptalks__namespace.Map(element, {
11051
- attribution: mapOptions.hideLogo ? false : MAP_ATTRIBUTION_TG,
11052
- // TODO: 使用GroupTileLayer, Map无法正确读取到当前显示的Layer的attribution, 故暂时不使用它
11053
- // baseLayer: new maptalks.GroupTileLayer('base', baseLayers),
11054
- baseLayer: baseLayer,
11255
+ // 默认的attribution不会显示GroupTileLayer的子layer的attribution, 故不显示, 使用自己的this.attributionControl来处理
11256
+ attribution: false,
11257
+ baseLayer: this.baseLayerGroup,
11055
11258
  // {@macro layer_baidu_spatial_reference}
11056
- spatialReference: baseLayer?.config().spatialReference,
11259
+ spatialReference: baseLayer?.options.spatialReference,
11057
11260
  // 参考google, marker和其他overlay分属不同layer, 并且marker位于overlay上方
11058
11261
  layers: [
11059
11262
  this.overlayLayer, this.markerLayer,
@@ -11062,11 +11265,60 @@ class TalksMap extends BaseMap {
11062
11265
  seamlessZoom: mapOptions.fractionalZoom ?? false,
11063
11266
  zoom: mapOptions.zoom,
11064
11267
  // 默认使用baseLayer的Zoom范围
11065
- minZoom: mapOptions.minZoom ?? baseLayer?.config().minZoom,
11066
- maxZoom: mapOptions.maxZoom ?? baseLayer?.config().maxZoom,
11268
+ minZoom: mapOptions.minZoom ?? baseLayer?.options.minZoom,
11269
+ maxZoom: mapOptions.maxZoom ?? baseLayer?.options.maxZoom,
11067
11270
  });
11068
11271
  this.setGestureHandling(mapOptions.gestureHandling);
11069
11272
  this.setEventTargetDelegate(new TalksEventTargetDelegate(this.map, this));
11273
+ this.attributionControl = new maptalks__namespace.control.Attribution(MAP_ATTRIBUTION_TG);
11274
+ this.map.addControl(this.attributionControl);
11275
+ this.setHideLogo(mapOptions.hideLogo ?? false);
11276
+ this.map.on('setbaselayer', this.onBaseLayerChanged);
11277
+ this.onBaseLayerChanged();
11278
+ }
11279
+ getCurrentBaseLayer() {
11280
+ return this.baseLayerGroup.layers.find(it => it.isVisible());
11281
+ }
11282
+ onBaseLayerChanged = () => {
11283
+ const baseLayer = this.getCurrentBaseLayer();
11284
+ if (!baseLayer)
11285
+ return;
11286
+ // 更新cacheBaseLayerId, attribution, spatialReference, 但并没有更新minZoom/maxZoom, 因为感觉必要性不大
11287
+ this.cachedBaseLayerId = baseLayer.getId();
11288
+ const layerAttribution = baseLayer.options.attribution;
11289
+ this.attributionControl.setContent(MAP_ATTRIBUTION_TG.content + (layerAttribution ? ` - ${layerAttribution}` : ''));
11290
+ if (this.map.getSpatialReference().options.projection !== baseLayer.getSpatialReference().options.projection) {
11291
+ console.debug('setSpatialReference', this.map.getSpatialReference().options, '==>', baseLayer.getSpatialReference().options);
11292
+ this.map.setSpatialReference(baseLayer.getSpatialReference().options);
11293
+ }
11294
+ };
11295
+ computeBaseLayerId(buildInMapTypeId = exports.BuildInMapTypeId.normal, theme = 'light') {
11296
+ const mapType = exports.MapType.BUILD_IN_MAP_TYPES.get(BuildInMapType.prototype.getId, buildInMapTypeId);
11297
+ if (theme === 'dark') {
11298
+ const darkOffset = exports.MapType.BUILD_IN_MAP_TYPES.values.length;
11299
+ // 遍历: 7, 6, 5, 4, 查找设置了值的暗色layerId
11300
+ for (let i = Math.min((mapType.index + darkOffset), this.baseLayoutIds.length - 1); i >= darkOffset; i--) {
11301
+ if (this.baseLayoutIds[i]) {
11302
+ return this.baseLayoutIds[i];
11303
+ }
11304
+ }
11305
+ }
11306
+ // 遍历: 3, 2, 1, 0, 查找设置了值的亮色layerId
11307
+ for (let i = Math.min(mapType.index, this.baseLayoutIds.length - 1); i >= 0; i--) {
11308
+ if (this.baseLayoutIds[i]) {
11309
+ return this.baseLayoutIds[i];
11310
+ }
11311
+ }
11312
+ return this.baseLayoutIds[0];
11313
+ }
11314
+ setBaseLayer(id, theme) {
11315
+ this.mapStyleTheme = theme;
11316
+ const baseLayerId = this.computeBaseLayerId(id, theme);
11317
+ const currentBaseLayerId = this.getCurrentBaseLayer()?.getId();
11318
+ if (currentBaseLayerId !== baseLayerId) {
11319
+ this.baseLayerGroup.layers.forEach((layer) => exports.Talks.setVisible(layer, layer.getId() === baseLayerId));
11320
+ this.onBaseLayerChanged();
11321
+ }
11070
11322
  }
11071
11323
  setGestureHandling(gestureHandling = exports.GestureHandlingOptions.auto) {
11072
11324
  if (gestureHandling === exports.GestureHandlingOptions.auto) {
@@ -11102,7 +11354,7 @@ class TalksMap extends BaseMap {
11102
11354
  return this.map;
11103
11355
  }
11104
11356
  get coordType() {
11105
- return talksBaseLayerIdToCoordType(this.currentBaseLayerId);
11357
+ return talksBaseLayerIdToCoordType(this.cachedBaseLayerId);
11106
11358
  }
11107
11359
  fromContainerPointToLatLng(point) {
11108
11360
  const coordinate = this.map.containerPointToCoordinate(new maptalks__namespace.Point(point.x, point.y));
@@ -11113,7 +11365,7 @@ class TalksMap extends BaseMap {
11113
11365
  return point; // maptalks.Point符合Point接口, 可以直接返回
11114
11366
  }
11115
11367
  setHideLogo(hideLogo) {
11116
- this.map.config('attribution', hideLogo ? false : MAP_ATTRIBUTION_TG);
11368
+ exports.Talks.setVisible(this.attributionControl, !hideLogo);
11117
11369
  }
11118
11370
  setFractionalZoom(enabled) {
11119
11371
  this.map.config('seamlessZoom', enabled);
@@ -11140,16 +11392,31 @@ class TalksMap extends BaseMap {
11140
11392
  this.map.setMaxZoom(zoom);
11141
11393
  }
11142
11394
  setMapStyle(mapStyle) {
11143
- // TODO: 2026/01/05 ipcjs 下一版再实现该功能
11395
+ if (mapStyle?.talks?.theme) {
11396
+ const mapType = this.getMapType();
11397
+ if (mapType instanceof BuildInMapType) {
11398
+ this.setBaseLayer(mapType.id, mapStyle.talks.theme);
11399
+ }
11400
+ else {
11401
+ console.log('自定义MapType不支持设置地图样式', mapType);
11402
+ }
11403
+ }
11144
11404
  }
11145
11405
  setBuildInMapTypeId(id) {
11146
- // TODO: 2026/01/05 ipcjs 下一版再实现该功能
11406
+ this.setBaseLayer(id, this.mapStyleTheme);
11147
11407
  }
11148
11408
  setMapType(mapType) {
11149
- // TODO: 2026/01/05 ipcjs 下一版再实现该功能
11409
+ if (mapType instanceof BuildInMapType) {
11410
+ this.setBaseLayer(mapType.getId(), this.mapStyleTheme);
11411
+ }
11150
11412
  }
11151
11413
  getMapType() {
11152
- // TODO: 2026/01/05 ipcjs 下一版再实现该功能
11414
+ const currentBaseLayerId = this.getCurrentBaseLayer()?.getId();
11415
+ const index = this.baseLayoutIds.findIndex(it => it === currentBaseLayerId);
11416
+ if (index !== -1) {
11417
+ return exports.MapType.BUILD_IN_MAP_TYPES.values[index % exports.MapType.BUILD_IN_MAP_TYPES.values.length];
11418
+ }
11419
+ // TODO: 2026/01/05 ipcjs 自定义MapType, 下一版再实现该功能
11153
11420
  return exports.MapType.NORMAL;
11154
11421
  }
11155
11422
  addLayer(layer) {
@@ -11181,22 +11448,6 @@ class TalksMap extends BaseMap {
11181
11448
  removeElementOverlay(overlay) {
11182
11449
  // TODO: 2026/01/05 ipcjs 下一版再实现该功能
11183
11450
  }
11184
- addOverlay(overlay) {
11185
- if (overlay.innerOverlay instanceof maptalks__namespace.ui.UIComponent) {
11186
- overlay.innerOverlay.addTo(this.map);
11187
- return;
11188
- }
11189
- const layer = overlay instanceof TalksMarker ? this.markerLayer : this.overlayLayer;
11190
- layer.addGeometry(overlay.innerOverlay);
11191
- }
11192
- removeOverlay(overlay) {
11193
- if (overlay.innerOverlay instanceof maptalks__namespace.ui.UIComponent) {
11194
- overlay.innerOverlay.remove();
11195
- return;
11196
- }
11197
- const layer = overlay instanceof TalksMarker ? this.markerLayer : this.overlayLayer;
11198
- layer.removeGeometry(overlay.innerOverlay);
11199
- }
11200
11451
  createMarker = TalksMarker.create;
11201
11452
  createMarkerClusterer(options) {
11202
11453
  return new TalksMarkerClusterer(this, options);
@@ -11280,17 +11531,20 @@ exports.TgMapFactory = void 0;
11280
11531
  case exports.TgMapType.here:
11281
11532
  return new HereMap($map, options);
11282
11533
  case exports.TgMapType.baiduFree:
11283
- return new TalksMap($map, options, ['baidu', 'osm']);
11534
+ return new TalksMap($map, options, ['baidu', 'amap-terrain', undefined, undefined, 'osm-dark']);
11284
11535
  case exports.TgMapType.googleFree:
11285
- return new TalksMap($map, options, ['google', 'osm']);
11536
+ return new TalksMap($map, options, ['google', 'osm-terrain', undefined, undefined, 'osm-dark']);
11286
11537
  case exports.TgMapType.amap:
11287
- return new TalksMap($map, options, ['amap']);
11538
+ return new TalksMap($map, options, ['amap', 'amap-terrain', undefined, undefined, 'osm-dark']);
11288
11539
  case exports.TgMapType.osm:
11289
- return new TalksMap($map, options, ['osm']);
11540
+ return new TalksMap($map, options, ['osm-light', 'osm-terrain', undefined, undefined, 'osm-dark']);
11290
11541
  case exports.TgMapType.yandex:
11291
- return new TalksMap($map, options, ['yandex']);
11292
- case exports.TgMapType.talks:
11293
- return new TalksMap($map, options, [getTgMapConfig().talks.layerId || 'bing']);
11542
+ return new TalksMap($map, options, ['yandex', undefined, undefined, undefined, 'osm-dark']);
11543
+ case exports.TgMapType.talks: {
11544
+ const hasDefinedFirstElement = (array) => !!(array && array.length && array[0]);
11545
+ const talks = getTgMapConfig().talks;
11546
+ return new TalksMap($map, options, hasDefinedFirstElement(talks.layerIds) ? talks.layerIds : [talks.layerId || 'bing']);
11547
+ }
11294
11548
  default:
11295
11549
  tgCommons.assertNever(type);
11296
11550
  }