csk-gis-frame-work 4.0.0

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.
Files changed (636) hide show
  1. package/baseSetting/config/mapConfig.js +48 -0
  2. package/baseSetting/gis-data/examples-data/3DTile/Tileset/tileset.json +124 -0
  3. package/baseSetting/gis-data/examples-data/client-analysis/buffer-hash-4.json +1 -0
  4. package/baseSetting/gis-data/examples-data/client-analysis/point.json +47 -0
  5. package/baseSetting/gis-data/examples-data/echarts/griddata.js +3 -0
  6. package/baseSetting/gis-data/examples-data/echarts/line-bus.json +1 -0
  7. package/baseSetting/gis-data/examples-data/echarts/weibo.geojson +1 -0
  8. package/baseSetting/gis-data/examples-data/echarts/weibo.json +1 -0
  9. package/baseSetting/gis-data/examples-data/echartsgl/beijing/buildings.xml +1 -0
  10. package/baseSetting/gis-data/examples-data/echartsgl/newyork/buildings.json +17178 -0
  11. package/baseSetting/gis-data/examples-data/echartsgl/shenzhen//346/267/261/345/234/263/350/275/250/350/277/271/347/272/277.json +24 -0
  12. package/baseSetting/gis-data/examples-data/echartsgl/shenzhen//351/201/223/350/267/25703.json +1949 -0
  13. package/baseSetting/gis-data/examples-data/geojson/animate-marker.json +15007 -0
  14. package/baseSetting/gis-data/examples-data/geojson/arc.js +256 -0
  15. package/baseSetting/gis-data/examples-data/geojson/chiacgo_bounds.geojson +9 -0
  16. package/baseSetting/gis-data/examples-data/geojson/china-city.geojson +355 -0
  17. package/baseSetting/gis-data/examples-data/geojson/china-xian.geojson +2428 -0
  18. package/baseSetting/gis-data/examples-data/geojson/china.geojson +42 -0
  19. package/baseSetting/gis-data/examples-data/geojson/countries.geojson +181 -0
  20. package/baseSetting/gis-data/examples-data/geojson/line-string.json +1020 -0
  21. package/baseSetting/gis-data/examples-data/geojson/washington_bounds.geojson +6 -0
  22. package/baseSetting/gis-data/examples-data/geojson/washington_point.geojson +153 -0
  23. package/baseSetting/gis-data/examples-data/geojson/wuhan_bounds.geojson +29 -0
  24. package/baseSetting/gis-data/examples-data/kml/Earthquake_2012.js +203 -0
  25. package/baseSetting/gis-data/examples-data/kml/KML_Samples.kml +915 -0
  26. package/baseSetting/gis-data/examples-data/mapbox/changestyle.json +2980 -0
  27. package/baseSetting/gis-data/examples-data/mapbox/sprite.json +3634 -0
  28. package/baseSetting/gis-data/examples-data/mapv/china-point.geojson +2 -0
  29. package/baseSetting/gis-data/examples-data/mapv/china-point.json +2 -0
  30. package/baseSetting/gis-data/examples-data/mapv/china.geojson +40 -0
  31. package/baseSetting/gis-data/examples-data/mapv/china.json +40 -0
  32. package/baseSetting/gis-data/examples-data/model/Airplane/Airplane.dae +333 -0
  33. package/baseSetting/gis-data/examples-data/model/Airplane/Airplane.gltf +802 -0
  34. package/baseSetting/gis-data/examples-data/model/fireExtinguisher.gltf +455 -0
  35. package/baseSetting/gis-data/sources_layers.js +2002 -0
  36. package/baseSetting/images/map/done.png +0 -0
  37. package/baseSetting/images/map/error.png +0 -0
  38. package/baseSetting/images/map/invalid.png +0 -0
  39. package/baseSetting/images/map/map.png +0 -0
  40. package/baseSetting/images/map/point.png +0 -0
  41. package/baseSetting/images/map/todo.png +0 -0
  42. package/baseSetting/style/DevMapConfig.js +33 -0
  43. package/baseSetting/style/getDefaultFonts.py +23 -0
  44. package/baseSetting/utils/TokenUtils.js +15 -0
  45. package/index.js +42 -0
  46. package/mapboxgl/js/common/AnnotationLayer.js +341 -0
  47. package/mapboxgl/js/common/BoundaryLayer.js +271 -0
  48. package/mapboxgl/js/common/ClusterLayer.js +498 -0
  49. package/mapboxgl/js/common/FlowLayer.js +234 -0
  50. package/mapboxgl/js/common/FlowingLayer.js +325 -0
  51. package/mapboxgl/js/common/HeatmapLayer.js +280 -0
  52. package/mapboxgl/js/common/ILayer.js +89 -0
  53. package/mapboxgl/js/common/LocationLayer.js +791 -0
  54. package/mapboxgl/js/common/PulserLayer.js +244 -0
  55. package/mapboxgl/js/common/SelectionLayer.js +315 -0
  56. package/mapboxgl/js/common/SimpleCircleLayer.js +465 -0
  57. package/mapboxgl/js/common/SimpleFillLayer.js +475 -0
  58. package/mapboxgl/js/common/SimpleLineLayer.js +430 -0
  59. package/mapboxgl/js/common/SimpleMarkerLayer.js +468 -0
  60. package/mapboxgl/js/common/StatsCircleLayer.js +351 -0
  61. package/mapboxgl/js/common/TrackingLayer.js +845 -0
  62. package/mapboxgl/js/common/VideoClusterLayer.js +539 -0
  63. package/mapboxgl/js/common/VideoLayer.js +334 -0
  64. package/mapboxgl/js/drainer/DrainEntityAnalystProvider.js +550 -0
  65. package/mapboxgl/js/drainer/DrainEntityProvider.js +557 -0
  66. package/mapboxgl/js/drainer/DrainEntityStatsLayer.js +144 -0
  67. package/mapboxgl/js/drainer/DrainUnitLayer.js +130 -0
  68. package/mapboxgl/js/drainer/DrainageEntityLayer.js +145 -0
  69. package/mapboxgl/js/drainer/DrainageEntityProvider.js +222 -0
  70. package/mapboxgl/js/drainer/DrainageUnitFlowLayer.js +137 -0
  71. package/mapboxgl/js/drainer/DrainageUnitlineLayer.js +154 -0
  72. package/mapboxgl/js/drainer/DrainageUnitlineProvider.js +140 -0
  73. package/mapboxgl/js/drainer/DrainerSearchProvider.js +274 -0
  74. package/mapboxgl/js/draw/CircleDrawing.js +238 -0
  75. package/mapboxgl/js/draw/DrawingProvider.js +533 -0
  76. package/mapboxgl/js/draw/DynamicBuffer.js +220 -0
  77. package/mapboxgl/js/draw/PointDrawing.js +189 -0
  78. package/mapboxgl/js/draw/PolygonDrawing.js +538 -0
  79. package/mapboxgl/js/draw/PolylineDrawing.js +597 -0
  80. package/mapboxgl/js/draw/RectangleDrawing.js +217 -0
  81. package/mapboxgl/js/draw/SplitPoylgon.js +214 -0
  82. package/mapboxgl/js/draw/mapConfig.js +240 -0
  83. package/mapboxgl/js/dynamic/BuildingsiteLayer.js +179 -0
  84. package/mapboxgl/js/dynamic/BusinessProvider.js +547 -0
  85. package/mapboxgl/js/dynamic/DefectLayer.js +137 -0
  86. package/mapboxgl/js/dynamic/EventLayer.js +151 -0
  87. package/mapboxgl/js/dynamic/StaffLayer.js +233 -0
  88. package/mapboxgl/js/dynamic/StoreLayer.js +143 -0
  89. package/mapboxgl/js/dynamic/VehicleLayer.js +236 -0
  90. package/mapboxgl/js/dynamic/WorkorderLayer.js +110 -0
  91. package/mapboxgl/js/editor/DeleteMarkerLayer.js +184 -0
  92. package/mapboxgl/js/editor/EditorProvider.js +2270 -0
  93. package/mapboxgl/js/editor/SurveyProvider.js +253 -0
  94. package/mapboxgl/js/equipment/AlarmLayer.js +117 -0
  95. package/mapboxgl/js/equipment/EquipCODLayer.js +119 -0
  96. package/mapboxgl/js/equipment/EquipDoorLayer.js +119 -0
  97. package/mapboxgl/js/equipment/EquipFloodedLayer.js +118 -0
  98. package/mapboxgl/js/equipment/EquipFlowLayer.js +119 -0
  99. package/mapboxgl/js/equipment/EquipFlowingLayer.js +103 -0
  100. package/mapboxgl/js/equipment/EquipLiquidLayer.js +121 -0
  101. package/mapboxgl/js/equipment/EquipNh3Layer.js +119 -0
  102. package/mapboxgl/js/equipment/EquipOtherLayer.js +123 -0
  103. package/mapboxgl/js/equipment/EquipPumpLayer.js +119 -0
  104. package/mapboxgl/js/equipment/EquipRaingaugeLayer.js +116 -0
  105. package/mapboxgl/js/equipment/EquipSpeedLayer.js +119 -0
  106. package/mapboxgl/js/equipment/EquipWellLayer.js +119 -0
  107. package/mapboxgl/js/equipment/EquipmentLayer.js +116 -0
  108. package/mapboxgl/js/equipment/EquipmentProvider.js +545 -0
  109. package/mapboxgl/js/equipment/EquippHLayer.js +119 -0
  110. package/mapboxgl/js/equipment/OverflowLayer.js +167 -0
  111. package/mapboxgl/js/equipment/WarnLayer.js +120 -0
  112. package/mapboxgl/js/event/EventBranchPipeLayer.js +108 -0
  113. package/mapboxgl/js/event/EventDefectLayer.js +119 -0
  114. package/mapboxgl/js/event/EventDrainerLayer.js +119 -0
  115. package/mapboxgl/js/event/EventLayer.js +123 -0
  116. package/mapboxgl/js/event/EventMixLayer.js +119 -0
  117. package/mapboxgl/js/event/EventOtherLayer.js +119 -0
  118. package/mapboxgl/js/event/EventOtherWaterLayer.js +109 -0
  119. package/mapboxgl/js/event/EventPolicyWaterLayer.js +119 -0
  120. package/mapboxgl/js/event/EventPourLayer.js +119 -0
  121. package/mapboxgl/js/event/EventProvider.js +426 -0
  122. package/mapboxgl/js/event/EventWaterLayer.js +108 -0
  123. package/mapboxgl/js/facility/DitchLayer.js +171 -0
  124. package/mapboxgl/js/facility/FacilityProvider.js +523 -0
  125. package/mapboxgl/js/facility/FlapLayer.js +196 -0
  126. package/mapboxgl/js/facility/GateLayer.js +166 -0
  127. package/mapboxgl/js/facility/InterceptionLayer.js +166 -0
  128. package/mapboxgl/js/facility/InterceptionsewLayer.js +166 -0
  129. package/mapboxgl/js/facility/OutfallLayer.js +166 -0
  130. package/mapboxgl/js/facility/PatrolareaLayer.js +177 -0
  131. package/mapboxgl/js/facility/RaininletLayer.js +166 -0
  132. package/mapboxgl/js/facility/StorageLayer.js +166 -0
  133. package/mapboxgl/js/geog/AreaBoundaryProvider.js +282 -0
  134. package/mapboxgl/js/geog/BoundaryProvider.js +266 -0
  135. package/mapboxgl/js/geog/GMLProvider.js +146 -0
  136. package/mapboxgl/js/geog/GeoJsonProvider.js +336 -0
  137. package/mapboxgl/js/geog/IconProvider.js +481 -0
  138. package/mapboxgl/js/geog/IndexedDBProvider.js +467 -0
  139. package/mapboxgl/js/geog/LayerProvider.js +275 -0
  140. package/mapboxgl/js/geog/LocationProvider.js +227 -0
  141. package/mapboxgl/js/geog/MapProvider.js +179 -0
  142. package/mapboxgl/js/geog/SelectionProvider.js +99 -0
  143. package/mapboxgl/js/geog/WKTProvider.js +180 -0
  144. package/mapboxgl/js/layers/CircleLayer.js +471 -0
  145. package/mapboxgl/js/layers/ClusterLayer.js +529 -0
  146. package/mapboxgl/js/layers/FillLayer.js +407 -0
  147. package/mapboxgl/js/layers/FlowingLayer.js +315 -0
  148. package/mapboxgl/js/layers/HeatmapLayer.js +263 -0
  149. package/mapboxgl/js/layers/IconClusterLayer.js +497 -0
  150. package/mapboxgl/js/layers/LineLayer.js +442 -0
  151. package/mapboxgl/js/layers/MarkerLayer.js +504 -0
  152. package/mapboxgl/js/layers/Pulser.js +84 -0
  153. package/mapboxgl/js/layers/PulserLayer.js +161 -0
  154. package/mapboxgl/js/layers/TextLayer.js +352 -0
  155. package/mapboxgl/js/pipe/BufferLayer.js +142 -0
  156. package/mapboxgl/js/pipe/DrainageAreaLayer.js +272 -0
  157. package/mapboxgl/js/pipe/DrainageAreaProvider.js +823 -0
  158. package/mapboxgl/js/pipe/DrainagePointLayer.js +258 -0
  159. package/mapboxgl/js/pipe/LayerManagerProvider.js +1499 -0
  160. package/mapboxgl/js/pipe/MapQueryProvider.js +879 -0
  161. package/mapboxgl/js/pipe/QueryResultsLayer.js +799 -0
  162. package/mapboxgl/js/pipeline/ConnholeLayer.js +134 -0
  163. package/mapboxgl/js/pipeline/LabelLayer.js +310 -0
  164. package/mapboxgl/js/pipeline/ManholeLayer.js +563 -0
  165. package/mapboxgl/js/pipeline/PipeflowLayer.js +490 -0
  166. package/mapboxgl/js/pipeline/PipelineErrorLayer.js +180 -0
  167. package/mapboxgl/js/pipeline/PipelineFlowLayer.js +213 -0
  168. package/mapboxgl/js/pipeline/PipelineLayer.js +509 -0
  169. package/mapboxgl/js/pipeline/PipenetErrorProvider.js +352 -0
  170. package/mapboxgl/js/pipeline/PipenetFaultProvider.js +219 -0
  171. package/mapboxgl/js/pipeline/PipenetInProvider.js +514 -0
  172. package/mapboxgl/js/pipeline/PipenetMixingFlowLayer.js +329 -0
  173. package/mapboxgl/js/pipeline/PipenetMixingLayer.js +155 -0
  174. package/mapboxgl/js/pipeline/PipenetMixingProvider.js +163 -0
  175. package/mapboxgl/js/pipeline/PipenetProvider.js +1042 -0
  176. package/mapboxgl/js/pipenet/PipenetAnalystProvider.js +393 -0
  177. package/mapboxgl/js/pipenet/PipenetConnectivityProvider.js +166 -0
  178. package/mapboxgl/js/pipenet/PipenetDownstreamProvider.js +276 -0
  179. package/mapboxgl/js/pipenet/PipenetFlowingLayer.js +312 -0
  180. package/mapboxgl/js/pipenet/PipenetServiceRangeProvider.js +386 -0
  181. package/mapboxgl/js/pipenet/PipenetUpdownstreamProvider.js +507 -0
  182. package/mapboxgl/js/pipenet/PipenetUpstreamProvider.js +311 -0
  183. package/mapboxgl/js/pipenet/PipenetWhereaboutsProvider.js +342 -0
  184. package/mapboxgl/js/plant/FlylineLayer.js +304 -0
  185. package/mapboxgl/js/plant/PlantLayer.js +166 -0
  186. package/mapboxgl/js/plant/PlantPumpProvider.js +788 -0
  187. package/mapboxgl/js/plant/PumpLayer.js +166 -0
  188. package/mapboxgl/js/plant/RuralSewageLayer.js +166 -0
  189. package/mapboxgl/js/plant/ServiceRangeLayer.js +130 -0
  190. package/mapboxgl/js/plant/VideoProvider.js +145 -0
  191. package/mapboxgl/js/three/ThreeGltfProvider.js +245 -0
  192. package/mapboxgl/js/utils/CesiumUtils.js +109 -0
  193. package/mapboxgl/js/utils/ColorUtils.js +48 -0
  194. package/mapboxgl/js/utils/CommonUtils.js +65 -0
  195. package/mapboxgl/js/utils/DataUtils.js +138 -0
  196. package/mapboxgl/js/utils/GeoJsonUtils.js +357 -0
  197. package/mapboxgl/js/utils/GeogUtils.js +300 -0
  198. package/mapboxgl/js/utils/LayerUtils.js +160 -0
  199. package/mapboxgl/js/utils/MapUtils.js +128 -0
  200. package/mapboxgl/js/utils/NetworkUtils.js +21 -0
  201. package/mapboxgl/js/utils/PipenetUtils.js +100 -0
  202. package/mapboxgl/js/utils/ProjUtils.js +32 -0
  203. package/mapboxgl/js/utils/SpatialRefUtils.js +198 -0
  204. package/mapboxgl/js/utils/SvgUtils.js +133 -0
  205. package/mapboxgl/js/utils/VerifyUtils.js +73 -0
  206. package/mapboxgl/js/widget/Pulser.js +88 -0
  207. package/mapboxgl/style/fonts/Microsoft YaHei/0-255.pbf +0 -0
  208. package/mapboxgl/style/fonts/Microsoft YaHei/1024-1279.pbf +0 -0
  209. package/mapboxgl/style/fonts/Microsoft YaHei/10240-10495.pbf +3 -0
  210. package/mapboxgl/style/fonts/Microsoft YaHei/10496-10751.pbf +3 -0
  211. package/mapboxgl/style/fonts/Microsoft YaHei/10752-11007.pbf +3 -0
  212. package/mapboxgl/style/fonts/Microsoft YaHei/11008-11263.pbf +3 -0
  213. package/mapboxgl/style/fonts/Microsoft YaHei/11264-11519.pbf +3 -0
  214. package/mapboxgl/style/fonts/Microsoft YaHei/11520-11775.pbf +3 -0
  215. package/mapboxgl/style/fonts/Microsoft YaHei/11776-12031.pbf +0 -0
  216. package/mapboxgl/style/fonts/Microsoft YaHei/12032-12287.pbf +3 -0
  217. package/mapboxgl/style/fonts/Microsoft YaHei/12288-12543.pbf +0 -0
  218. package/mapboxgl/style/fonts/Microsoft YaHei/12544-12799.pbf +0 -0
  219. package/mapboxgl/style/fonts/Microsoft YaHei/1280-1535.pbf +3 -0
  220. package/mapboxgl/style/fonts/Microsoft YaHei/12800-13055.pbf +0 -0
  221. package/mapboxgl/style/fonts/Microsoft YaHei/13056-13311.pbf +0 -0
  222. package/mapboxgl/style/fonts/Microsoft YaHei/13312-13567.pbf +0 -0
  223. package/mapboxgl/style/fonts/Microsoft YaHei/13568-13823.pbf +0 -0
  224. package/mapboxgl/style/fonts/Microsoft YaHei/13824-14079.pbf +0 -0
  225. package/mapboxgl/style/fonts/Microsoft YaHei/14080-14335.pbf +0 -0
  226. package/mapboxgl/style/fonts/Microsoft YaHei/14336-14591.pbf +0 -0
  227. package/mapboxgl/style/fonts/Microsoft YaHei/14592-14847.pbf +0 -0
  228. package/mapboxgl/style/fonts/Microsoft YaHei/14848-15103.pbf +0 -0
  229. package/mapboxgl/style/fonts/Microsoft YaHei/15104-15359.pbf +0 -0
  230. package/mapboxgl/style/fonts/Microsoft YaHei/1536-1791.pbf +3 -0
  231. package/mapboxgl/style/fonts/Microsoft YaHei/15360-15615.pbf +0 -0
  232. package/mapboxgl/style/fonts/Microsoft YaHei/15616-15871.pbf +0 -0
  233. package/mapboxgl/style/fonts/Microsoft YaHei/15872-16127.pbf +0 -0
  234. package/mapboxgl/style/fonts/Microsoft YaHei/16128-16383.pbf +0 -0
  235. package/mapboxgl/style/fonts/Microsoft YaHei/16384-16639.pbf +0 -0
  236. package/mapboxgl/style/fonts/Microsoft YaHei/16640-16895.pbf +0 -0
  237. package/mapboxgl/style/fonts/Microsoft YaHei/16896-17151.pbf +0 -0
  238. package/mapboxgl/style/fonts/Microsoft YaHei/17152-17407.pbf +0 -0
  239. package/mapboxgl/style/fonts/Microsoft YaHei/17408-17663.pbf +0 -0
  240. package/mapboxgl/style/fonts/Microsoft YaHei/17664-17919.pbf +0 -0
  241. package/mapboxgl/style/fonts/Microsoft YaHei/1792-2047.pbf +3 -0
  242. package/mapboxgl/style/fonts/Microsoft YaHei/17920-18175.pbf +0 -0
  243. package/mapboxgl/style/fonts/Microsoft YaHei/18176-18431.pbf +0 -0
  244. package/mapboxgl/style/fonts/Microsoft YaHei/18432-18687.pbf +0 -0
  245. package/mapboxgl/style/fonts/Microsoft YaHei/18688-18943.pbf +0 -0
  246. package/mapboxgl/style/fonts/Microsoft YaHei/18944-19199.pbf +0 -0
  247. package/mapboxgl/style/fonts/Microsoft YaHei/19200-19455.pbf +0 -0
  248. package/mapboxgl/style/fonts/Microsoft YaHei/19456-19711.pbf +0 -0
  249. package/mapboxgl/style/fonts/Microsoft YaHei/19712-19967.pbf +0 -0
  250. package/mapboxgl/style/fonts/Microsoft YaHei/19968-20223.pbf +0 -0
  251. package/mapboxgl/style/fonts/Microsoft YaHei/20224-20479.pbf +0 -0
  252. package/mapboxgl/style/fonts/Microsoft YaHei/2048-2303.pbf +3 -0
  253. package/mapboxgl/style/fonts/Microsoft YaHei/20480-20735.pbf +0 -0
  254. package/mapboxgl/style/fonts/Microsoft YaHei/20736-20991.pbf +0 -0
  255. package/mapboxgl/style/fonts/Microsoft YaHei/20992-21247.pbf +0 -0
  256. package/mapboxgl/style/fonts/Microsoft YaHei/21248-21503.pbf +0 -0
  257. package/mapboxgl/style/fonts/Microsoft YaHei/21504-21759.pbf +0 -0
  258. package/mapboxgl/style/fonts/Microsoft YaHei/21760-22015.pbf +0 -0
  259. package/mapboxgl/style/fonts/Microsoft YaHei/22016-22271.pbf +0 -0
  260. package/mapboxgl/style/fonts/Microsoft YaHei/22272-22527.pbf +154 -9
  261. package/mapboxgl/style/fonts/Microsoft YaHei/22528-22783.pbf +0 -0
  262. package/mapboxgl/style/fonts/Microsoft YaHei/22784-23039.pbf +0 -0
  263. package/mapboxgl/style/fonts/Microsoft YaHei/2304-2559.pbf +3 -0
  264. package/mapboxgl/style/fonts/Microsoft YaHei/23040-23295.pbf +0 -0
  265. package/mapboxgl/style/fonts/Microsoft YaHei/23296-23551.pbf +0 -0
  266. package/mapboxgl/style/fonts/Microsoft YaHei/23552-23807.pbf +0 -0
  267. package/mapboxgl/style/fonts/Microsoft YaHei/23808-24063.pbf +0 -0
  268. package/mapboxgl/style/fonts/Microsoft YaHei/24064-24319.pbf +0 -0
  269. package/mapboxgl/style/fonts/Microsoft YaHei/24320-24575.pbf +0 -0
  270. package/mapboxgl/style/fonts/Microsoft YaHei/24576-24831.pbf +0 -0
  271. package/mapboxgl/style/fonts/Microsoft YaHei/24832-25087.pbf +0 -0
  272. package/mapboxgl/style/fonts/Microsoft YaHei/25088-25343.pbf +0 -0
  273. package/mapboxgl/style/fonts/Microsoft YaHei/25344-25599.pbf +0 -0
  274. package/mapboxgl/style/fonts/Microsoft YaHei/256-511.pbf +0 -0
  275. package/mapboxgl/style/fonts/Microsoft YaHei/2560-2815.pbf +3 -0
  276. package/mapboxgl/style/fonts/Microsoft YaHei/25600-25855.pbf +0 -0
  277. package/mapboxgl/style/fonts/Microsoft YaHei/25856-26111.pbf +0 -0
  278. package/mapboxgl/style/fonts/Microsoft YaHei/26112-26367.pbf +0 -0
  279. package/mapboxgl/style/fonts/Microsoft YaHei/26368-26623.pbf +0 -0
  280. package/mapboxgl/style/fonts/Microsoft YaHei/26624-26879.pbf +0 -0
  281. package/mapboxgl/style/fonts/Microsoft YaHei/26880-27135.pbf +0 -0
  282. package/mapboxgl/style/fonts/Microsoft YaHei/27136-27391.pbf +0 -0
  283. package/mapboxgl/style/fonts/Microsoft YaHei/27392-27647.pbf +0 -0
  284. package/mapboxgl/style/fonts/Microsoft YaHei/27648-27903.pbf +0 -0
  285. package/mapboxgl/style/fonts/Microsoft YaHei/27904-28159.pbf +0 -0
  286. package/mapboxgl/style/fonts/Microsoft YaHei/2816-3071.pbf +3 -0
  287. package/mapboxgl/style/fonts/Microsoft YaHei/28160-28415.pbf +0 -0
  288. package/mapboxgl/style/fonts/Microsoft YaHei/28416-28671.pbf +0 -0
  289. package/mapboxgl/style/fonts/Microsoft YaHei/28672-28927.pbf +0 -0
  290. package/mapboxgl/style/fonts/Microsoft YaHei/28928-29183.pbf +0 -0
  291. package/mapboxgl/style/fonts/Microsoft YaHei/29184-29439.pbf +0 -0
  292. package/mapboxgl/style/fonts/Microsoft YaHei/29440-29695.pbf +0 -0
  293. package/mapboxgl/style/fonts/Microsoft YaHei/29696-29951.pbf +0 -0
  294. package/mapboxgl/style/fonts/Microsoft YaHei/29952-30207.pbf +0 -0
  295. package/mapboxgl/style/fonts/Microsoft YaHei/30208-30463.pbf +0 -0
  296. package/mapboxgl/style/fonts/Microsoft YaHei/30464-30719.pbf +0 -0
  297. package/mapboxgl/style/fonts/Microsoft YaHei/3072-3327.pbf +3 -0
  298. package/mapboxgl/style/fonts/Microsoft YaHei/30720-30975.pbf +0 -0
  299. package/mapboxgl/style/fonts/Microsoft YaHei/30976-31231.pbf +0 -0
  300. package/mapboxgl/style/fonts/Microsoft YaHei/31232-31487.pbf +0 -0
  301. package/mapboxgl/style/fonts/Microsoft YaHei/31488-31743.pbf +0 -0
  302. package/mapboxgl/style/fonts/Microsoft YaHei/31744-31999.pbf +0 -0
  303. package/mapboxgl/style/fonts/Microsoft YaHei/32000-32255.pbf +0 -0
  304. package/mapboxgl/style/fonts/Microsoft YaHei/32256-32511.pbf +0 -0
  305. package/mapboxgl/style/fonts/Microsoft YaHei/32512-32767.pbf +0 -0
  306. package/mapboxgl/style/fonts/Microsoft YaHei/32768-33023.pbf +0 -0
  307. package/mapboxgl/style/fonts/Microsoft YaHei/33024-33279.pbf +0 -0
  308. package/mapboxgl/style/fonts/Microsoft YaHei/3328-3583.pbf +3 -0
  309. package/mapboxgl/style/fonts/Microsoft YaHei/33280-33535.pbf +0 -0
  310. package/mapboxgl/style/fonts/Microsoft YaHei/33536-33791.pbf +0 -0
  311. package/mapboxgl/style/fonts/Microsoft YaHei/33792-34047.pbf +0 -0
  312. package/mapboxgl/style/fonts/Microsoft YaHei/34048-34303.pbf +0 -0
  313. package/mapboxgl/style/fonts/Microsoft YaHei/34304-34559.pbf +0 -0
  314. package/mapboxgl/style/fonts/Microsoft YaHei/34560-34815.pbf +0 -0
  315. package/mapboxgl/style/fonts/Microsoft YaHei/34816-35071.pbf +0 -0
  316. package/mapboxgl/style/fonts/Microsoft YaHei/35072-35327.pbf +0 -0
  317. package/mapboxgl/style/fonts/Microsoft YaHei/35328-35583.pbf +0 -0
  318. package/mapboxgl/style/fonts/Microsoft YaHei/35584-35839.pbf +0 -0
  319. package/mapboxgl/style/fonts/Microsoft YaHei/3584-3839.pbf +3 -0
  320. package/mapboxgl/style/fonts/Microsoft YaHei/35840-36095.pbf +0 -0
  321. package/mapboxgl/style/fonts/Microsoft YaHei/36096-36351.pbf +0 -0
  322. package/mapboxgl/style/fonts/Microsoft YaHei/36352-36607.pbf +0 -0
  323. package/mapboxgl/style/fonts/Microsoft YaHei/36608-36863.pbf +0 -0
  324. package/mapboxgl/style/fonts/Microsoft YaHei/36864-37119.pbf +0 -0
  325. package/mapboxgl/style/fonts/Microsoft YaHei/37120-37375.pbf +0 -0
  326. package/mapboxgl/style/fonts/Microsoft YaHei/37376-37631.pbf +0 -0
  327. package/mapboxgl/style/fonts/Microsoft YaHei/37632-37887.pbf +0 -0
  328. package/mapboxgl/style/fonts/Microsoft YaHei/37888-38143.pbf +0 -0
  329. package/mapboxgl/style/fonts/Microsoft YaHei/38144-38399.pbf +0 -0
  330. package/mapboxgl/style/fonts/Microsoft YaHei/3840-4095.pbf +3 -0
  331. package/mapboxgl/style/fonts/Microsoft YaHei/38400-38655.pbf +0 -0
  332. package/mapboxgl/style/fonts/Microsoft YaHei/38656-38911.pbf +0 -0
  333. package/mapboxgl/style/fonts/Microsoft YaHei/38912-39167.pbf +0 -0
  334. package/mapboxgl/style/fonts/Microsoft YaHei/39168-39423.pbf +0 -0
  335. package/mapboxgl/style/fonts/Microsoft YaHei/39424-39679.pbf +0 -0
  336. package/mapboxgl/style/fonts/Microsoft YaHei/39680-39935.pbf +0 -0
  337. package/mapboxgl/style/fonts/Microsoft YaHei/39936-40191.pbf +0 -0
  338. package/mapboxgl/style/fonts/Microsoft YaHei/40192-40447.pbf +0 -0
  339. package/mapboxgl/style/fonts/Microsoft YaHei/40448-40703.pbf +0 -0
  340. package/mapboxgl/style/fonts/Microsoft YaHei/40704-40959.pbf +0 -0
  341. package/mapboxgl/style/fonts/Microsoft YaHei/4096-4351.pbf +3 -0
  342. package/mapboxgl/style/fonts/Microsoft YaHei/40960-41215.pbf +3 -0
  343. package/mapboxgl/style/fonts/Microsoft YaHei/41216-41471.pbf +3 -0
  344. package/mapboxgl/style/fonts/Microsoft YaHei/41472-41727.pbf +3 -0
  345. package/mapboxgl/style/fonts/Microsoft YaHei/41728-41983.pbf +3 -0
  346. package/mapboxgl/style/fonts/Microsoft YaHei/41984-42239.pbf +3 -0
  347. package/mapboxgl/style/fonts/Microsoft YaHei/42240-42495.pbf +3 -0
  348. package/mapboxgl/style/fonts/Microsoft YaHei/42496-42751.pbf +3 -0
  349. package/mapboxgl/style/fonts/Microsoft YaHei/42752-43007.pbf +3 -0
  350. package/mapboxgl/style/fonts/Microsoft YaHei/43008-43263.pbf +3 -0
  351. package/mapboxgl/style/fonts/Microsoft YaHei/43264-43519.pbf +3 -0
  352. package/mapboxgl/style/fonts/Microsoft YaHei/4352-4607.pbf +3 -0
  353. package/mapboxgl/style/fonts/Microsoft YaHei/43520-43775.pbf +3 -0
  354. package/mapboxgl/style/fonts/Microsoft YaHei/43776-44031.pbf +3 -0
  355. package/mapboxgl/style/fonts/Microsoft YaHei/44032-44287.pbf +3 -0
  356. package/mapboxgl/style/fonts/Microsoft YaHei/44288-44543.pbf +3 -0
  357. package/mapboxgl/style/fonts/Microsoft YaHei/44544-44799.pbf +3 -0
  358. package/mapboxgl/style/fonts/Microsoft YaHei/44800-45055.pbf +3 -0
  359. package/mapboxgl/style/fonts/Microsoft YaHei/45056-45311.pbf +3 -0
  360. package/mapboxgl/style/fonts/Microsoft YaHei/45312-45567.pbf +3 -0
  361. package/mapboxgl/style/fonts/Microsoft YaHei/45568-45823.pbf +3 -0
  362. package/mapboxgl/style/fonts/Microsoft YaHei/45824-46079.pbf +3 -0
  363. package/mapboxgl/style/fonts/Microsoft YaHei/4608-4863.pbf +3 -0
  364. package/mapboxgl/style/fonts/Microsoft YaHei/46080-46335.pbf +3 -0
  365. package/mapboxgl/style/fonts/Microsoft YaHei/46336-46591.pbf +3 -0
  366. package/mapboxgl/style/fonts/Microsoft YaHei/46592-46847.pbf +3 -0
  367. package/mapboxgl/style/fonts/Microsoft YaHei/46848-47103.pbf +3 -0
  368. package/mapboxgl/style/fonts/Microsoft YaHei/47104-47359.pbf +3 -0
  369. package/mapboxgl/style/fonts/Microsoft YaHei/47360-47615.pbf +3 -0
  370. package/mapboxgl/style/fonts/Microsoft YaHei/47616-47871.pbf +3 -0
  371. package/mapboxgl/style/fonts/Microsoft YaHei/47872-48127.pbf +3 -0
  372. package/mapboxgl/style/fonts/Microsoft YaHei/48128-48383.pbf +3 -0
  373. package/mapboxgl/style/fonts/Microsoft YaHei/48384-48639.pbf +3 -0
  374. package/mapboxgl/style/fonts/Microsoft YaHei/4864-5119.pbf +3 -0
  375. package/mapboxgl/style/fonts/Microsoft YaHei/48640-48895.pbf +3 -0
  376. package/mapboxgl/style/fonts/Microsoft YaHei/48896-49151.pbf +3 -0
  377. package/mapboxgl/style/fonts/Microsoft YaHei/49152-49407.pbf +3 -0
  378. package/mapboxgl/style/fonts/Microsoft YaHei/49408-49663.pbf +3 -0
  379. package/mapboxgl/style/fonts/Microsoft YaHei/49664-49919.pbf +3 -0
  380. package/mapboxgl/style/fonts/Microsoft YaHei/49920-50175.pbf +3 -0
  381. package/mapboxgl/style/fonts/Microsoft YaHei/50176-50431.pbf +3 -0
  382. package/mapboxgl/style/fonts/Microsoft YaHei/50432-50687.pbf +3 -0
  383. package/mapboxgl/style/fonts/Microsoft YaHei/50688-50943.pbf +3 -0
  384. package/mapboxgl/style/fonts/Microsoft YaHei/50944-51199.pbf +3 -0
  385. package/mapboxgl/style/fonts/Microsoft YaHei/512-767.pbf +0 -0
  386. package/mapboxgl/style/fonts/Microsoft YaHei/5120-5375.pbf +3 -0
  387. package/mapboxgl/style/fonts/Microsoft YaHei/51200-51455.pbf +3 -0
  388. package/mapboxgl/style/fonts/Microsoft YaHei/51456-51711.pbf +3 -0
  389. package/mapboxgl/style/fonts/Microsoft YaHei/51712-51967.pbf +3 -0
  390. package/mapboxgl/style/fonts/Microsoft YaHei/51968-52223.pbf +3 -0
  391. package/mapboxgl/style/fonts/Microsoft YaHei/52224-52479.pbf +3 -0
  392. package/mapboxgl/style/fonts/Microsoft YaHei/52480-52735.pbf +3 -0
  393. package/mapboxgl/style/fonts/Microsoft YaHei/52736-52991.pbf +3 -0
  394. package/mapboxgl/style/fonts/Microsoft YaHei/52992-53247.pbf +3 -0
  395. package/mapboxgl/style/fonts/Microsoft YaHei/53248-53503.pbf +3 -0
  396. package/mapboxgl/style/fonts/Microsoft YaHei/53504-53759.pbf +3 -0
  397. package/mapboxgl/style/fonts/Microsoft YaHei/5376-5631.pbf +3 -0
  398. package/mapboxgl/style/fonts/Microsoft YaHei/53760-54015.pbf +3 -0
  399. package/mapboxgl/style/fonts/Microsoft YaHei/54016-54271.pbf +3 -0
  400. package/mapboxgl/style/fonts/Microsoft YaHei/54272-54527.pbf +3 -0
  401. package/mapboxgl/style/fonts/Microsoft YaHei/54528-54783.pbf +3 -0
  402. package/mapboxgl/style/fonts/Microsoft YaHei/54784-55039.pbf +3 -0
  403. package/mapboxgl/style/fonts/Microsoft YaHei/55040-55295.pbf +3 -0
  404. package/mapboxgl/style/fonts/Microsoft YaHei/55296-55551.pbf +3 -0
  405. package/mapboxgl/style/fonts/Microsoft YaHei/55552-55807.pbf +3 -0
  406. package/mapboxgl/style/fonts/Microsoft YaHei/55808-56063.pbf +3 -0
  407. package/mapboxgl/style/fonts/Microsoft YaHei/56064-56319.pbf +3 -0
  408. package/mapboxgl/style/fonts/Microsoft YaHei/5632-5887.pbf +3 -0
  409. package/mapboxgl/style/fonts/Microsoft YaHei/56320-56575.pbf +3 -0
  410. package/mapboxgl/style/fonts/Microsoft YaHei/56576-56831.pbf +3 -0
  411. package/mapboxgl/style/fonts/Microsoft YaHei/56832-57087.pbf +3 -0
  412. package/mapboxgl/style/fonts/Microsoft YaHei/57088-57343.pbf +3 -0
  413. package/mapboxgl/style/fonts/Microsoft YaHei/57344-57599.pbf +3 -0
  414. package/mapboxgl/style/fonts/Microsoft YaHei/57600-57855.pbf +3 -0
  415. package/mapboxgl/style/fonts/Microsoft YaHei/57856-58111.pbf +3 -0
  416. package/mapboxgl/style/fonts/Microsoft YaHei/58112-58367.pbf +3 -0
  417. package/mapboxgl/style/fonts/Microsoft YaHei/58368-58623.pbf +3 -0
  418. package/mapboxgl/style/fonts/Microsoft YaHei/58624-58879.pbf +3 -0
  419. package/mapboxgl/style/fonts/Microsoft YaHei/5888-6143.pbf +3 -0
  420. package/mapboxgl/style/fonts/Microsoft YaHei/58880-59135.pbf +3 -0
  421. package/mapboxgl/style/fonts/Microsoft YaHei/59136-59391.pbf +3 -0
  422. package/mapboxgl/style/fonts/Microsoft YaHei/59392-59647.pbf +3 -0
  423. package/mapboxgl/style/fonts/Microsoft YaHei/59648-59903.pbf +3 -0
  424. package/mapboxgl/style/fonts/Microsoft YaHei/59904-60159.pbf +3 -0
  425. package/mapboxgl/style/fonts/Microsoft YaHei/60160-60415.pbf +3 -0
  426. package/mapboxgl/style/fonts/Microsoft YaHei/60416-60671.pbf +3 -0
  427. package/mapboxgl/style/fonts/Microsoft YaHei/60672-60927.pbf +3 -0
  428. package/mapboxgl/style/fonts/Microsoft YaHei/60928-61183.pbf +3 -0
  429. package/mapboxgl/style/fonts/Microsoft YaHei/61184-61439.pbf +3 -0
  430. package/mapboxgl/style/fonts/Microsoft YaHei/6144-6399.pbf +3 -0
  431. package/mapboxgl/style/fonts/Microsoft YaHei/61440-61695.pbf +3 -0
  432. package/mapboxgl/style/fonts/Microsoft YaHei/61696-61951.pbf +3 -0
  433. package/mapboxgl/style/fonts/Microsoft YaHei/61952-62207.pbf +3 -0
  434. package/mapboxgl/style/fonts/Microsoft YaHei/62208-62463.pbf +3 -0
  435. package/mapboxgl/style/fonts/Microsoft YaHei/62464-62719.pbf +3 -0
  436. package/mapboxgl/style/fonts/Microsoft YaHei/62720-62975.pbf +3 -0
  437. package/mapboxgl/style/fonts/Microsoft YaHei/62976-63231.pbf +3 -0
  438. package/mapboxgl/style/fonts/Microsoft YaHei/63232-63487.pbf +3 -0
  439. package/mapboxgl/style/fonts/Microsoft YaHei/63488-63743.pbf +3 -0
  440. package/mapboxgl/style/fonts/Microsoft YaHei/63744-63999.pbf +0 -0
  441. package/mapboxgl/style/fonts/Microsoft YaHei/6400-6655.pbf +3 -0
  442. package/mapboxgl/style/fonts/Microsoft YaHei/64000-64255.pbf +0 -0
  443. package/mapboxgl/style/fonts/Microsoft YaHei/64256-64511.pbf +3 -0
  444. package/mapboxgl/style/fonts/Microsoft YaHei/64512-64767.pbf +3 -0
  445. package/mapboxgl/style/fonts/Microsoft YaHei/64768-65023.pbf +3 -0
  446. package/mapboxgl/style/fonts/Microsoft YaHei/65024-65279.pbf +0 -0
  447. package/mapboxgl/style/fonts/Microsoft YaHei/65280-65535.pbf +0 -0
  448. package/mapboxgl/style/fonts/Microsoft YaHei/6656-6911.pbf +3 -0
  449. package/mapboxgl/style/fonts/Microsoft YaHei/6912-7167.pbf +3 -0
  450. package/mapboxgl/style/fonts/Microsoft YaHei/7168-7423.pbf +3 -0
  451. package/mapboxgl/style/fonts/Microsoft YaHei/7424-7679.pbf +3 -0
  452. package/mapboxgl/style/fonts/Microsoft YaHei/768-1023.pbf +0 -0
  453. package/mapboxgl/style/fonts/Microsoft YaHei/7680-7935.pbf +0 -0
  454. package/mapboxgl/style/fonts/Microsoft YaHei/7936-8191.pbf +3 -0
  455. package/mapboxgl/style/fonts/Microsoft YaHei/8192-8447.pbf +0 -0
  456. package/mapboxgl/style/fonts/Microsoft YaHei/8448-8703.pbf +0 -0
  457. package/mapboxgl/style/fonts/Microsoft YaHei/8704-8959.pbf +0 -0
  458. package/mapboxgl/style/fonts/Microsoft YaHei/8960-9215.pbf +0 -0
  459. package/mapboxgl/style/fonts/Microsoft YaHei/9216-9471.pbf +0 -0
  460. package/mapboxgl/style/fonts/Microsoft YaHei/9472-9727.pbf +0 -0
  461. package/mapboxgl/style/fonts/Microsoft YaHei/9728-9983.pbf +0 -0
  462. package/mapboxgl/style/fonts/Microsoft YaHei/9984-10239.pbf +4 -0
  463. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/0-255.pbf +0 -0
  464. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/1024-1279.pbf +0 -0
  465. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/10240-10495.pbf +3 -0
  466. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/10496-10751.pbf +3 -0
  467. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/10752-11007.pbf +3 -0
  468. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/11008-11263.pbf +3 -0
  469. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/11264-11519.pbf +3 -0
  470. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/11520-11775.pbf +3 -0
  471. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/11776-12031.pbf +3 -0
  472. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/12032-12287.pbf +3 -0
  473. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/12288-12543.pbf +0 -0
  474. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/12544-12799.pbf +0 -0
  475. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/1280-1535.pbf +0 -0
  476. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/12800-13055.pbf +0 -0
  477. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/13056-13311.pbf +0 -0
  478. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/13312-13567.pbf +3 -0
  479. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/13568-13823.pbf +3 -0
  480. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/13824-14079.pbf +3 -0
  481. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/14080-14335.pbf +3 -0
  482. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/14336-14591.pbf +3 -0
  483. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/14592-14847.pbf +3 -0
  484. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/14848-15103.pbf +3 -0
  485. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/16384-16639.pbf +3 -0
  486. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/16640-16895.pbf +3 -0
  487. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/16896-17151.pbf +3 -0
  488. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/17152-17407.pbf +3 -0
  489. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/1792-2047.pbf +3 -0
  490. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/18432-18687.pbf +3 -0
  491. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/19968-20223.pbf +0 -0
  492. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/20224-20479.pbf +0 -0
  493. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/2048-2303.pbf +3 -0
  494. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/20736-20991.pbf +0 -0
  495. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/21248-21503.pbf +0 -0
  496. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/21504-21759.pbf +0 -0
  497. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/21760-22015.pbf +0 -0
  498. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/22016-22271.pbf +0 -0
  499. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/22272-22527.pbf +118 -19
  500. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/22528-22783.pbf +0 -0
  501. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/22784-23039.pbf +0 -0
  502. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/2304-2559.pbf +0 -0
  503. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/23040-23295.pbf +0 -0
  504. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/23552-23807.pbf +0 -0
  505. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/24064-24319.pbf +0 -0
  506. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/24320-24575.pbf +0 -0
  507. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/24576-24831.pbf +0 -0
  508. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/24832-25087.pbf +0 -0
  509. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/25088-25343.pbf +0 -0
  510. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/25344-25599.pbf +0 -0
  511. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/256-511.pbf +0 -0
  512. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/2560-2815.pbf +0 -0
  513. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/25600-25855.pbf +0 -0
  514. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/25856-26111.pbf +0 -0
  515. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/26112-26367.pbf +0 -0
  516. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/26368-26623.pbf +0 -0
  517. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/2816-3071.pbf +0 -0
  518. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/3072-3327.pbf +0 -0
  519. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/31744-31999.pbf +0 -0
  520. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/32000-32255.pbf +0 -0
  521. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/32256-32511.pbf +0 -0
  522. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/32512-32767.pbf +0 -0
  523. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/32768-33023.pbf +0 -0
  524. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/33024-33279.pbf +0 -0
  525. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/3328-3583.pbf +0 -0
  526. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/33536-33791.pbf +0 -0
  527. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/33792-34047.pbf +0 -0
  528. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/34048-34303.pbf +0 -0
  529. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/34304-34559.pbf +0 -0
  530. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/34560-34815.pbf +0 -0
  531. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/34816-35071.pbf +0 -0
  532. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/35072-35327.pbf +0 -0
  533. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/35328-35583.pbf +0 -0
  534. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/3584-3839.pbf +0 -0
  535. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/35840-36095.pbf +0 -0
  536. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/36096-36351.pbf +0 -0
  537. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/36352-36607.pbf +0 -0
  538. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/36608-36863.pbf +0 -0
  539. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/37120-37375.pbf +0 -0
  540. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/37376-37631.pbf +0 -0
  541. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/37888-38143.pbf +0 -0
  542. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/38144-38399.pbf +0 -0
  543. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/38400-38655.pbf +0 -0
  544. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/38656-38911.pbf +0 -0
  545. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/38912-39167.pbf +0 -0
  546. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/39168-39423.pbf +0 -0
  547. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/39424-39679.pbf +0 -0
  548. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/39680-39935.pbf +0 -0
  549. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/39936-40191.pbf +0 -0
  550. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/40448-40703.pbf +0 -0
  551. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/40704-40959.pbf +0 -0
  552. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/40960-41215.pbf +3 -0
  553. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/41216-41471.pbf +3 -0
  554. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/41472-41727.pbf +3 -0
  555. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/41728-41983.pbf +3 -0
  556. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/41984-42239.pbf +3 -0
  557. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/42240-42495.pbf +3 -0
  558. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/42496-42751.pbf +3 -0
  559. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/42752-43007.pbf +3 -0
  560. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/43008-43263.pbf +3 -0
  561. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/43264-43519.pbf +3 -0
  562. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/43776-44031.pbf +3 -0
  563. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/44032-44287.pbf +0 -0
  564. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/44288-44543.pbf +0 -0
  565. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/44544-44799.pbf +0 -0
  566. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/44800-45055.pbf +0 -0
  567. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/45056-45311.pbf +0 -0
  568. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/45312-45567.pbf +0 -0
  569. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/45568-45823.pbf +0 -0
  570. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/46080-46335.pbf +0 -0
  571. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/46336-46591.pbf +0 -0
  572. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/46592-46847.pbf +0 -0
  573. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/46848-47103.pbf +0 -0
  574. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/47104-47359.pbf +0 -0
  575. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/47360-47615.pbf +0 -0
  576. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/47872-48127.pbf +0 -0
  577. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/48128-48383.pbf +78 -0
  578. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/48384-48639.pbf +0 -0
  579. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/49664-49919.pbf +0 -0
  580. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/50176-50431.pbf +0 -0
  581. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/50432-50687.pbf +0 -0
  582. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/50688-50943.pbf +0 -0
  583. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/50944-51199.pbf +0 -0
  584. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/512-767.pbf +0 -0
  585. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/5120-5375.pbf +3 -0
  586. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/51200-51455.pbf +0 -0
  587. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/51456-51711.pbf +117 -4
  588. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/51712-51967.pbf +0 -0
  589. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/51968-52223.pbf +0 -0
  590. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/52480-52735.pbf +0 -0
  591. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/52736-52991.pbf +0 -0
  592. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/52992-53247.pbf +0 -0
  593. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/5376-5631.pbf +3 -0
  594. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/5632-5887.pbf +3 -0
  595. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/5888-6143.pbf +3 -0
  596. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/6144-6399.pbf +3 -0
  597. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/6400-6655.pbf +3 -0
  598. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/6656-6911.pbf +3 -0
  599. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/6912-7167.pbf +3 -0
  600. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/7168-7423.pbf +3 -0
  601. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/7424-7679.pbf +3 -0
  602. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/7680-7935.pbf +0 -0
  603. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/8192-8447.pbf +0 -0
  604. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/8448-8703.pbf +0 -0
  605. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/8704-8959.pbf +0 -0
  606. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/8960-9215.pbf +0 -0
  607. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/9216-9471.pbf +0 -0
  608. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/9472-9727.pbf +0 -0
  609. package/mapboxgl/style/fonts/Open Sans Regular,Arial Unicode MS Regular/9984-10239.pbf +0 -0
  610. package/mapboxgl/style/sprite/dark/sprite.json +1 -0
  611. package/mapboxgl/style/sprite/dark/sprite.png +0 -0
  612. package/mapboxgl/style/sprite/dark/sprite@2x.json +1 -0
  613. package/mapboxgl/style/sprite/dark/sprite@2x.png +0 -0
  614. package/mapboxgl/utils/mapbox.js +3821 -0
  615. package/mapboxgl/utils/mapbox_native.js +2037 -0
  616. package/mapboxgl/utils/mapboxgl.md +138 -0
  617. package/mapgis/js/datalayer/arcgis-layer/ArcGISMapImageLayer.js +586 -0
  618. package/mapgis/js/datalayer/arcgis-layer/ArcGISTileLayer.js +515 -0
  619. package/mapgis/js/datalayer/arcgis-layer/ArcGISVectorTileLayer.js +907 -0
  620. package/mapgis/js/datalayer/common-layer/Cesium3DTilesCacheLayer.js +1036 -0
  621. package/mapgis/js/datalayer/common-layer/EchartsLayer.js +861 -0
  622. package/mapgis/js/datalayer/igs-layer/IGSFeatureLayer.js +863 -0
  623. package/mapgis/js/datalayer/igs-layer/IGSImageryLayer.js +460 -0
  624. package/mapgis/js/datalayer/igs-layer/IGSImageryTileLayer.js +404 -0
  625. package/mapgis/js/datalayer/igs-layer/IGSMapImageLayer.js +607 -0
  626. package/mapgis/js/datalayer/igs-layer/IGSTileLayer.js +397 -0
  627. package/mapgis/js/datalayer/igs-layer/IGSVectorTileLayer.js +580 -0
  628. package/mapgis/js/datalayer/igs-layer/ISSceneLayer.js +328 -0
  629. package/mapgis/js/datalayer/igs-layer/ImageryLayer.js +463 -0
  630. package/mapgis/js/datalayer/igs-layer/ImageryTileLayer.js +413 -0
  631. package/mapgis/js/datalayer/index.js +206 -0
  632. package/mapgis/js/datalayer/ogc-layer/wfsLayer.js +670 -0
  633. package/mapgis/js/datalayer/ogc-layer/wmsLayer.js +418 -0
  634. package/mapgis/js/datalayer/ogc-layer/wmtsLayer.js +419 -0
  635. package/mapgis/utils/mapgis-common.js +2945 -0
  636. package/package.json +31 -0
@@ -0,0 +1,3821 @@
1
+ import mapConfig from "../../baseSetting/config/mapConfig.js";
2
+ import {
3
+ base_sources,
4
+ business_layers,
5
+ business_sources,
6
+ Dark_Layers,
7
+ Dark_Sources,
8
+ Image_Layers,
9
+ LayerConfig,
10
+ Light_Layers,
11
+ Light_Sources,
12
+ Vector_Layers,
13
+ } from "../../baseSetting/gis-data/sources_layers.js";
14
+ import {
15
+ Dark_Style,
16
+ Light_Style,
17
+ } from "../../baseSetting/style/DevMapConfig.js";
18
+ import TokenUtils from "../../baseSetting/utils/TokenUtils.js";
19
+ import {Scene, Mapbox} from '@antv/l7'
20
+
21
+ // 图标资源
22
+ const point_icon = require('../../baseSetting/images/map/point.png');
23
+ const img_todo = require('../../baseSetting/images/map/todo.png');
24
+ const img_done = require('../../baseSetting/images/map/done.png');
25
+ const img_invalid = require('../../baseSetting/images/map/invalid.png');
26
+ const img_error = require('../../baseSetting/images/map/error.png');
27
+ let map = null
28
+ let antv7Scene = null
29
+ let pendingRequests = new Set();
30
+ const throttleDelay = 300; // 300ms 内相同瓦片不重复请求
31
+
32
+ // 颜色配置 TODO: 是否增加亮色/暗色的配置
33
+ const actual_color = '#7ed321';
34
+ const plan_color_valid = '#3a6bdb';
35
+ const plan_color_invalid = '#9b9b9b';
36
+
37
+ /**
38
+ * MapboxGL 地图工具集
39
+ * 按 map layer toolFunction 分类组织的工具函数集合
40
+ *
41
+ * @description
42
+ * 一、地图初始化与生命周期 - create / loadMapboxResources / initMap / createAntVL7Scene / getMap / getAntV7Scene / disposeMap
43
+ * 二、瓦片坐标与边界工具 - isValidTile / tile2lonlat / boundsIntersect
44
+ * 三、底图与图层源管理 - formatBaseSource / getGeoserverSources / getGeoserverSource / updateBaseMapVisibility / addTiles / changeMap / clearOverlays / updateEventAndAlarmLayerIndex / switchLayerVisible / addGeojsonSourceToMap
45
+ * 四、图标与标记 - getFeature / hideLogo / addImageSource / addMarker
46
+ * 五、服务URL构建 - joinWmtsUrl / joinTmsUrl / getTmsUrl / joinWfsUrl / getWfsQueryUrl
47
+ * 六、样式与主题切换 - setStyle / changeStyle / _changeStyle / setLayoutProperty / setPaintProperty / setFog / _setFog / setDEM / _loadDEM
48
+ * 七、巡检业务绘制 - setZoom / drawPatrolTask / drawPatrol / drawPatrolTaskInGaoDe / drawPatrolInGaoDe / placePoint
49
+ * 八、地图交互与搜索(POI) - addSearch / executeSearch / drawPOIResults / clearPOIResults / showSearchResults / clearSearchResults / focusOnPOI
50
+ * 九、点位标记与拖拽 - getMapboxPoints / hitPoint / _enablePointDragging
51
+ * 十、绘制工具(polyline) - renderLine / _enableLineEditing / _disableLineEditing / removeLine
52
+ * 十一、绘制工具(point) - renderPoint / _enablePointEditing / _disablePointEditing / removePoint
53
+ * 十二、绘制工具(polygon) - renderPolygon / _enablePolygonEditing / _disablePolygonEditing / removePolygon
54
+ * 十三、网格与辅助工具 - _drawGridWithCenterLabels / clearGridWithCenterLabels / countMidFromLine / resetCenterAndZoom
55
+ * 十四、相机与视角控制 - enableScrollWheelZoom / initialize / flyInitialize / initBearing / overlook / flyToOrigin / flyToTarget / flyTo / changeMode / locationArea
56
+ * 十五、地图导出 - _compositeSnapshotCanvas / exportBlob / exportBase64
57
+ */
58
+ export default {
59
+ // ==================== 配置属性 ====================
60
+ workspace: mapConfig.workspace,
61
+ mapType: mapConfig.mapType || "vector",
62
+ vectorSignalStr: ['vec', 'cva'],
63
+ imageSignalStr: ['img', 'cia'],
64
+ map_srid: mapConfig.map_srid,
65
+ business_srid: mapConfig.business_srid,
66
+ mbMap: null,
67
+ styleUrl: mapConfig.mapUrl + '/mapbox-gl/style',
68
+ sceneConfig: mapConfig.sceneConfig,
69
+ opts: {},
70
+ _customPopup: null,
71
+
72
+ // ==================== 一、地图初始化与生命周期 ====================
73
+
74
+ /**
75
+ * 创建地图实例
76
+ * theme = 'dark'时 将使用离线暗色底图瓦片,将mapConfig中的isOnline设置为false,此时默认使用文件服务器上的暗色瓦片资源
77
+ * theme = 'light'时 将使用在线亮色底图瓦片,将mapConfig中的isOnline设置为true,此时默认使用天地图资源
78
+ * theme = 'light'时 将使用在线亮色底图瓦片,将mapConfig中的isOnline设置为false,此时默认使用文件服务器上的亮色瓦片资源
79
+ * @param opts
80
+ * @param callback
81
+ */
82
+ create: function (opts, callback) {
83
+ this.opts = opts
84
+ if (mapConfig.noMap) {
85
+ this.$message.info("未配置地图")
86
+ alert("未配置地图")
87
+ } else {
88
+ if (typeof mapboxgl == 'undefined') {
89
+ // 使用 Promise 确保资源加载完成后再执行后续逻辑
90
+ this.loadMapboxResources().then(() => {
91
+ this.initMap(opts, callback);
92
+ }).catch((error) => {
93
+ console.error("地图资源加载失败:", error);
94
+ callback && callback();
95
+ });
96
+ } else {
97
+ this.initMap(opts, callback);
98
+ }
99
+ }
100
+ },
101
+
102
+
103
+ loadMapboxResources: function () {
104
+ return new Promise((resolve, reject) => {
105
+ const script = document.createElement("script");
106
+ script.src = mapConfig.mapUrl + "/mapbox-gl/mapbox-gl.js";
107
+
108
+ const link = document.createElement("link");
109
+ link.href = mapConfig.mapUrl + "/mapbox-gl/mapbox-gl.css";
110
+ link.rel = "stylesheet";
111
+
112
+ // 风格样式文件
113
+ const linkSearch = document.createElement("link");
114
+ linkSearch.href = mapConfig.mapUrl + "/mapbox-gl/gis-" + this.opts.theme + ".css";
115
+ linkSearch.rel = "stylesheet";
116
+
117
+ let scriptLoaded = false;
118
+ let linkLoaded = false;
119
+ let linkSearchLoaded = false;
120
+
121
+ const checkComplete = () => {
122
+ if (scriptLoaded && linkLoaded && linkSearchLoaded) {
123
+ resolve();
124
+ }
125
+ };
126
+
127
+ script.onload = () => {
128
+ scriptLoaded = true;
129
+ checkComplete();
130
+ };
131
+
132
+ link.onload = () => {
133
+ linkLoaded = true;
134
+ checkComplete();
135
+ };
136
+
137
+ linkSearch.onload = () => {
138
+ linkSearchLoaded = true;
139
+ checkComplete();
140
+ };
141
+
142
+ script.onerror = () => reject(new Error("Mapbox GL JS 加载失败"));
143
+ link.onerror = () => reject(new Error("Mapbox GL CSS 加载失败"));
144
+ linkSearch.onerror = () => reject(new Error("gis公共样式 加载失败"));
145
+
146
+ document.body.appendChild(script);
147
+ document.body.appendChild(link);
148
+ document.body.appendChild(linkSearch);
149
+ });
150
+ },
151
+
152
+ /**
153
+ * 初始化地图
154
+ * @param opts
155
+ * @param callback
156
+ */
157
+ initMap: function (opts, callback) {
158
+ let baseSources = {}, baseLayers = [];
159
+ const customStyle = opts.theme === "dark" ? Dark_Style : Light_Style;
160
+
161
+ if (mapConfig.isOnline) {
162
+ const basemapType = mapConfig.map_srid === 'EPSG:3857' ? 'w' : 'c';
163
+
164
+ baseSources = {};
165
+ baseLayers = [];
166
+
167
+ this.vectorSignalStr.forEach(signal => {
168
+ baseSources['tdt_vec_' + signal + '_tiles'] = {
169
+ type: 'raster',
170
+ tiles: [
171
+ 'https://t0.tianditu.gov.cn/' + signal + '_' + basemapType + '/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + signal + '&STYLE=default&TILEMATRIXSET=' + basemapType + '&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TokenUtils.TDT_token,
172
+ ],
173
+ scheme: 'xyz',
174
+ minzoom: 0,
175
+ maxzoom: mapConfig.maxOnlineZoom,
176
+ tileSize: 256
177
+ }
178
+ baseLayers.push({
179
+ id: 'tdt_vec_' + signal + '_tiles',
180
+ type: 'raster',
181
+ source: 'tdt_vec_' + signal + '_tiles',
182
+ minzoom: 0,
183
+ maxzoom: mapConfig.maxOnlineZoom,
184
+ })
185
+ })
186
+
187
+ this.imageSignalStr.forEach(signal => {
188
+ baseSources['tdt_img_' + signal + '_tiles'] = {
189
+ type: 'raster',
190
+ tiles: [
191
+ 'https://t0.tianditu.gov.cn/' + signal + '_' + basemapType + '/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=' + signal + '&STYLE=default&TILEMATRIXSET=' + basemapType + '&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TokenUtils.TDT_token,
192
+ ],
193
+ scheme: 'xyz',
194
+ minzoom: 0,
195
+ maxzoom: mapConfig.maxOnlineZoom,
196
+ tileSize: 256
197
+ }
198
+ baseLayers.push({
199
+ id: 'tdt_img_' + signal + '_tiles',
200
+ type: 'raster',
201
+ source: 'tdt_img_' + signal + '_tiles',
202
+ minzoom: 0,
203
+ maxzoom: mapConfig.maxOnlineZoom,
204
+ })
205
+ })
206
+ } else {
207
+ baseSources = opts.theme === "dark" ? this.getGeoserverSources(Dark_Sources) : {...this.formatBaseSource(base_sources), ...this.getGeoserverSources(Light_Sources)};
208
+ baseLayers = opts.theme === "dark" ? Dark_Layers : Light_Layers;
209
+ }
210
+
211
+ // let businessSources = this.getGeoserverSources(business_sources[opts.theme])
212
+ // let businessLayers = business_layers[opts.theme];
213
+ let businessLayers = [];
214
+ const mapId = opts.mapId;
215
+
216
+ mapboxgl.accessToken = TokenUtils.MapboxGL_AccessToken;
217
+ console.log('baseSources, baseLayers', baseSources, baseLayers);
218
+ mapboxgl.config.MAX_PARALLEL_IMAGE_REQUESTS = 256;
219
+
220
+ map = new mapboxgl.Map({
221
+ container: mapId,
222
+ minZoom: mapConfig.minZoom,
223
+ maxZoom: mapConfig.isOnline ? mapConfig.maxOnlineZoom : mapConfig.maxZoom,
224
+ zoom: mapConfig.zoom,
225
+ center: mapConfig.center,
226
+ maxBounds: [
227
+ [mapConfig.mapExtent[0], mapConfig.mapExtent[1]],
228
+ [mapConfig.mapExtent[2], mapConfig.mapExtent[3]]
229
+ ],
230
+ pitch: mapConfig.pitch,
231
+ bearing: mapConfig.bearing,
232
+ preserveDrawingBuffer: true,
233
+ constrainMode: 'width-and-height',
234
+ renderWorldCopies: false,
235
+ dragRotate: false, // 允许拖动旋转
236
+ touchZoom: true,
237
+ touchRotate: false,
238
+ style: {
239
+ version: 8,
240
+ name: "mb_map_style",
241
+ sprite: this.styleUrl + "/sprite/" + opts.theme + "/sprite",
242
+ glyphs: this.styleUrl + "/fonts/{fontstack}/{range}.pbf",
243
+ transition: {
244
+ duration: 300,
245
+ delay: 0,
246
+ },
247
+ sources: {
248
+ ...baseSources,
249
+ // ...businessSources,
250
+ },
251
+ layers: baseLayers
252
+ },
253
+ attributionControl: false,
254
+ // 👇 在这里配置 transformRequest
255
+ transformRequest: (url, resourceType) => {
256
+ // 仅处理瓦片请求 (可选,避免影响字体、精灵图等其他资源)
257
+ if (resourceType === 'Tile') {
258
+ // 1. 判断 URL 是否包含您的瓦片服务地址
259
+ if (url.includes('.pbf')) {
260
+ // 2. 尝试解析 URL 中的 z, x, y 参数
261
+ const urlObj = new URL(url);
262
+ const pathParts = urlObj.pathname.split('/');
263
+ const z = parseInt(pathParts[pathParts.length - 3]); // 根据实际路径结构调整
264
+ const x = parseInt(pathParts[pathParts.length - 2]);
265
+ const y = parseInt(pathParts[pathParts.length - 1].split('.')[0]);
266
+
267
+ // 3. 在这里写您的逻辑:判断 z/x/y 是否在有效范围内
268
+ this.isValidTile(z, x, y, url)
269
+ }
270
+ }
271
+ // 对于正常的请求,直接返回 url (或不做处理)
272
+ // return { url: url };
273
+ }
274
+ });
275
+
276
+ this.setStyle(map);
277
+ this.addImageSource(map)
278
+ map._customStyle = customStyle
279
+
280
+ map.on('load', () => {
281
+ if (mapConfig.isOnline) {
282
+ this.updateBaseMapVisibility(this.mapType);
283
+ }
284
+
285
+ if (businessLayers.length > 0) {
286
+ this.addBusinessLayer(map, businessLayers);
287
+ }
288
+
289
+ map.on('click', (pos) => {
290
+ window.currentLocation = [pos.lngLat.lng, pos.lngLat.lat]
291
+ })
292
+
293
+ map.on('zoom', () => {
294
+ const currentZoom = map.getZoom();
295
+ if (currentZoom > mapConfig.maxZoom) {
296
+ map.setZoom(mapConfig.maxZoom);
297
+ }
298
+ });
299
+
300
+ map.on('zoomend', () => {
301
+ const currentZoom = map.getZoom();
302
+ if (currentZoom >= mapConfig.maxZoom) {
303
+ map.flyTo({
304
+ zoom: mapConfig.maxZoom,
305
+ duration: 0
306
+ });
307
+ }
308
+ });
309
+
310
+
311
+ if (this.sceneConfig.useAntVL7Scene) {
312
+ antv7Scene = this.createAntVL7Scene(opts.mapId, map)
313
+ }
314
+
315
+ this.hideLogo()
316
+ map.resize()
317
+
318
+ if (antv7Scene) {
319
+ antv7Scene.on('loaded', () => {
320
+ callback && callback(map, antv7Scene);
321
+ })
322
+ } else {
323
+ callback && callback(map, null);
324
+ }
325
+
326
+ });
327
+
328
+ //@csk 瓦片请求优化(节流)
329
+ map.on('tile_request', (e) => {
330
+ const url = e.url;
331
+ if (pendingRequests.has(url)) {
332
+ e.preventDefault(); // 阻止重复请求
333
+ return;
334
+ }
335
+ pendingRequests.add(url);
336
+ setTimeout(() => pendingRequests.delete(url), throttleDelay);
337
+ });
338
+ },
339
+
340
+ createAntVL7Scene: function (mapId, map) {
341
+ // 立即返回 scene 对象,外部可以通过 scene.on('loaded') 监听加载完成
342
+ return new Scene({
343
+ id: mapId,
344
+ antialias: true, // 👈 关键!启用硬件抗锯齿
345
+ preserveDrawingBuffer: true,
346
+ map: new Mapbox({
347
+ mapInstance: map,
348
+ }),
349
+ WebGLParams: {
350
+ antialias: true
351
+ },
352
+ // 关闭默认 L7 Logo
353
+ logoVisible: false,
354
+ });
355
+ },
356
+
357
+
358
+ getMap: function () {
359
+ return map;
360
+ },
361
+
362
+
363
+ getAntV7Scene: function () {
364
+ return antv7Scene;
365
+ },
366
+
367
+
368
+ disposeMap: function () {
369
+ if (map) {
370
+ map.remove();
371
+ }
372
+ },
373
+
374
+
375
+ // ==================== 二、瓦片坐标与边界工具 ====================
376
+
377
+ isValidTile: function (z, x, y, url) {
378
+ // 在这里写你的判断逻辑
379
+ // 例如:mapConfig.mapExtent获取地图的经纬度范围从而判断z,x,y是否在有效范围内,如果是返回正确的url,否则返回一个空的图片
380
+ const mapBounds = mapConfig.mapExtent;
381
+ const tileBounds = this.tile2lonlat(x, y, z);
382
+ if (this.boundsIntersect(tileBounds, mapBounds)) {
383
+ return {
384
+ url: url
385
+ }
386
+ } else {
387
+ // 返回一个空的透明图片 Data URL,阻止实际的网络请求
388
+ return {
389
+ url: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
390
+ };
391
+ }
392
+ },
393
+
394
+
395
+ tile2lonlat: function (x, y, z) {
396
+ // 计算瓦片左上角的经纬度
397
+ const n = Math.pow(2, z);
398
+ const lon1 = (x / n) * 360 - 180;
399
+ const lat1 = Math.atan(Math.sinh(Math.PI * (1 - 2 * y / n))) * (180 / Math.PI);
400
+
401
+ // 计算瓦片右下角的经纬度
402
+ const lon2 = ((x + 1) / n) * 360 - 180;
403
+ const lat2 = Math.atan(Math.sinh(Math.PI * (1 - 2 * (y + 1) / n))) * (180 / Math.PI);
404
+
405
+ // Mapbox GL JS 使用 TMS 方案,y 轴是反的,需要转换
406
+ // 如果你的服务是 XYZ 方案,请注释下面的 lat 转换
407
+ const tileSize = 256;
408
+ const tileCount = Math.pow(2, z);
409
+ const yTMS = tileCount - 1 - y;
410
+
411
+ // 重新计算 TMS 对应的经纬度
412
+ const lat1TMS = Math.atan(Math.sinh(Math.PI * (1 - 2 * yTMS / n))) * (180 / Math.PI);
413
+ const lat2TMS = Math.atan(Math.sinh(Math.PI * (1 - 2 * (yTMS + 1) / n))) * (180 / Math.PI);
414
+
415
+ return [lon1, lat2TMS, lon2, lat1TMS];
416
+ },
417
+
418
+
419
+ boundsIntersect: function (bounds1, bounds2) {
420
+ // bounds 格式: [minLng, minLat, maxLng, maxLat]
421
+ return !(
422
+ bounds1[0] > bounds2[2] || // 左 > 右
423
+ bounds1[2] < bounds2[0] || // 右 < 左
424
+ bounds1[1] > bounds2[3] || // 下 > 上
425
+ bounds1[3] < bounds2[1] // 上 < 下
426
+ );
427
+ },
428
+
429
+
430
+ // ==================== 三、底图与图层源管理 ====================
431
+
432
+ formatBaseSource: function (sources) {
433
+ for (let lyrName in sources) {
434
+ // 瓦片服务地址为空时,使用默认地址,否则使用geoserver地址
435
+ if (!sources[lyrName].hasOwnProperty('tiles')) {
436
+ let tiles = this.joinTmsUrl(lyrName);
437
+ sources[lyrName].tiles = [tiles];
438
+ }
439
+ }
440
+ return sources
441
+ },
442
+
443
+
444
+ getGeoserverSources: function (configs) {
445
+ const dataSources = {};
446
+ configs.filter(src => !src.category).forEach((ds) => {
447
+ // 获取数据源对象
448
+ const sourceObj = this.getGeoserverSource(ds);
449
+ if (sourceObj) {
450
+ dataSources[ds.id] = sourceObj;
451
+ }
452
+ });
453
+
454
+ return dataSources;
455
+ },
456
+
457
+
458
+ getGeoserverSource: function (options) {
459
+ switch (options.type) {
460
+ case 'raster': { // GeoServer-栅格瓦片服务
461
+ return {
462
+ type: options.type,
463
+ scheme: options.scheme || 'xyz',
464
+ tiles: [
465
+ this.joinWmtsUrl(options.geoLayer, options.workspace)
466
+ ],
467
+ minzoom: options.minZoom || 0,
468
+ maxzoom: options.maxZoom || 22
469
+ };
470
+ }
471
+ case 'vector': { // GeoServer-矢量瓦片服务
472
+ return {
473
+ type: options.type,
474
+ scheme: options.scheme || 'tms',
475
+ tiles: [
476
+ this.joinTmsUrl(options.geoLayer, options.workspace)
477
+ ],
478
+ minzoom: options.minZoom || 0,
479
+ maxzoom: options.maxZoom || 22
480
+ };
481
+ }
482
+ case 'geojson': { // GeoServer-WFS服务
483
+ return {
484
+ type: options.type,
485
+ data: this.joinWfsUrl(options.geoLayer, options.category)
486
+ };
487
+ }
488
+ default:
489
+ return null;
490
+ }
491
+ },
492
+
493
+ /**
494
+ * 更新底图可见性
495
+ * @param {String} type - 底图类型:'vector' 或 'image'
496
+ */
497
+ updateBaseMapVisibility: function (type) {
498
+ if (!map || !mapConfig.isOnline) return;
499
+
500
+ const vecLayerIds = this.vectorSignalStr.map(signal => 'tdt_vec_' + signal + '_tiles');
501
+ const imgLayerIds = this.imageSignalStr.map(signal => 'tdt_img_' + signal + '_tiles');
502
+
503
+ vecLayerIds.forEach(layerId => {
504
+ if (map.getLayer(layerId)) {
505
+ const visibility = type === 'vector' ? 'visible' : 'none';
506
+ map.setLayoutProperty(layerId, 'visibility', visibility);
507
+ }
508
+ });
509
+
510
+ imgLayerIds.forEach(layerId => {
511
+ if (map.getLayer(layerId)) {
512
+ const visibility = type === 'image' ? 'visible' : 'none';
513
+ map.setLayoutProperty(layerId, 'visibility', visibility);
514
+ }
515
+ });
516
+ },
517
+
518
+ addTiles: function (map) {
519
+ if (!map) return;
520
+
521
+ // 添加自定义瓦片图层
522
+ map.addSource('custom-tiles', {
523
+ type: 'raster',
524
+ tiles: ['/images/tiles/{z}/{x}/{y}.png'],
525
+ tileSize: 256
526
+ });
527
+
528
+ map.addLayer({
529
+ id: 'custom-tiles-layer',
530
+ type: 'raster',
531
+ source: 'custom-tiles',
532
+ minzoom: 0,
533
+ maxzoom: 22
534
+ });
535
+ },
536
+
537
+ /*
538
+ * 切换底图
539
+ * @param {String} type -目标底图类型
540
+ */
541
+ changeMap: function (type) {
542
+ if (!map || type === this.mapType) return;
543
+
544
+ if (mapConfig.isOnline) {
545
+ this.updateBaseMapVisibility(type);
546
+ } else {
547
+ let changedLayers = null;
548
+ switch (type) {
549
+ case 'vector':
550
+ changedLayers = Vector_Layers;
551
+ break;
552
+ case 'image':
553
+ changedLayers = Image_Layers;
554
+ break;
555
+ default:
556
+ return;
557
+ }
558
+
559
+ changedLayers.forEach(layer => {
560
+ if (map.getLayer(layer.id)) {
561
+ map.setLayoutProperty(layer.id, 'visibility', layer.visibility);
562
+ }
563
+ });
564
+ }
565
+
566
+ this.mapType = type;
567
+ },
568
+
569
+ addBusinessLayer: function (map, businessLayers) {
570
+ businessLayers.forEach(layer => {
571
+ map.addLayer(layer)
572
+ })
573
+ },
574
+
575
+
576
+ clearOverlays: function () {
577
+ // 批量清除所有巡检相关的动态图层(ID包含patrol-track-前缀)
578
+ const layers = map.getStyle().layers;
579
+ layers.forEach(layer => {
580
+ if (layer.id.includes('patrol-track-')) {
581
+ map.removeLayer(layer.id);
582
+ if (layer.source && layer.source.includes('patrol-track-')) {
583
+ map.removeSource(layer.source);
584
+ }
585
+ }
586
+ });
587
+ },
588
+
589
+
590
+ updateEventAndAlarmLayerIndex: function (layerIds) {
591
+ const layers = map.getStyle().layers;
592
+ layerIds.forEach(layerId => {
593
+ map.moveLayer(layerId, layers[layers.length - 1].id);
594
+ });
595
+ },
596
+
597
+ switchLayerVisible: function (layerIdArray = []) {
598
+ const busilayers = business_layers[this.opts.theme];
599
+ if (layerIdArray.length === 0) {
600
+ busilayers.forEach(layer => {
601
+ map.setLayoutProperty(layer.id, 'visibility', 'visible');
602
+ })
603
+ } else {
604
+ busilayers.forEach(layer => {
605
+ if (layerIdArray.includes(layer.id)) {
606
+ map.setLayoutProperty(layer.id, 'visibility', 'visible');
607
+ } else {
608
+ map.setLayoutProperty(layer.id, 'visibility', 'none');
609
+ }
610
+ })
611
+ }
612
+ },
613
+
614
+ addGeojsonSourceToMap: function (sourceId, geojson) {
615
+ gisMap.addSource(sourceId, {
616
+ type: 'geojson',
617
+ data: geojson
618
+ })
619
+ },
620
+
621
+ // 源数据获取后统一加载到地图出口
622
+ addLayerToMap: function (sourceId, styleConfig) {
623
+ const layerConfig = {...styleConfig, source: sourceId}
624
+ console.log('layerConfig', layerConfig);
625
+ gisMap.addLayer(layerConfig)
626
+ },
627
+
628
+ // ==================== 四、图标与标记 ====================
629
+
630
+ getFeature: function (e) {
631
+ // 获取点击位置的要素
632
+ const features = map.queryRenderedFeatures(e.point);
633
+
634
+ if (features.length > 0) {
635
+ const feature = features[0];
636
+ console.log('点击的要素:', feature.properties);
637
+ return feature
638
+ }
639
+ },
640
+
641
+
642
+ hideLogo: function () {
643
+ console.log('logo is hidden')
644
+ let controls = map._controls;
645
+ controls.forEach(control => {
646
+ // 去除logo控件
647
+ if ('_updateLogo' in control) {
648
+ map.removeControl(control)
649
+ }
650
+
651
+ // 去除attribute控件
652
+ if ('_attribHTML' in control) {
653
+ map.removeControl(control)
654
+ }
655
+ })
656
+ },
657
+
658
+
659
+ addImageSource: function (map) {
660
+ // 添加图标到地图
661
+ if (!map.hasImage('img_done')) {
662
+ map.loadImage(img_done, (error, image) => {
663
+ if (error) throw error;
664
+ map.addImage('img_done', image);
665
+ });
666
+ }
667
+
668
+ if (!map.hasImage('img_error')) {
669
+ map.loadImage(img_error, (error, image) => {
670
+ if (error) throw error;
671
+ map.addImage('img_error', image);
672
+ });
673
+ }
674
+
675
+ if (!map.hasImage('img_invalid')) {
676
+ map.loadImage(img_invalid, (error, image) => {
677
+ if (error) throw error;
678
+ map.addImage('img_invalid', image);
679
+ });
680
+ }
681
+
682
+ if (!map.hasImage('img_todo')) {
683
+ map.loadImage(img_todo, (error, image) => {
684
+ if (error) throw error;
685
+ map.addImage('img_todo', image);
686
+ });
687
+ }
688
+ },
689
+
690
+
691
+ addMarker: function (data, customIcon, customIconName) {
692
+ console.log('addMarker>>>>>>')
693
+ // 清除之前的标记图层和数据源
694
+ if (map.getLayer('marker-point')) {
695
+ map.removeLayer('marker-point');
696
+ }
697
+ if (map.getSource('marker-point')) {
698
+ map.removeSource('marker-point');
699
+ }
700
+
701
+ if (data.longitude && data.latitude) {
702
+ // 确保图标已加载到地图中
703
+ if (!map.hasImage('add_marker_icon')) {
704
+ map.loadImage(point_icon, (error, image) => {
705
+ if (error) throw error;
706
+ map.addImage('add_marker_icon', image);
707
+ });
708
+ }
709
+
710
+ if (!map.hasImage('custom-icon')) {
711
+ map.loadImage(customIcon, (error, image) => {
712
+ if (error) throw error;
713
+ map.addImage(customIconName || 'custom-icon', image);
714
+ });
715
+ }
716
+
717
+ // 创建GeoJSON数据源
718
+ const geojson = {
719
+ type: 'FeatureCollection',
720
+ features: [{
721
+ type: 'Feature',
722
+ geometry: {
723
+ type: 'Point',
724
+ coordinates: [data.longitude, data.latitude]
725
+ },
726
+ properties: {}
727
+ }]
728
+ };
729
+
730
+ // 添加数据源
731
+ map.addSource('marker-point', {
732
+ type: 'geojson',
733
+ data: geojson
734
+ });
735
+
736
+ // 添加图层显示标记点(使用自定义图标)
737
+ map.addLayer({
738
+ id: 'marker-point',
739
+ type: 'symbol',
740
+ source: 'marker-point',
741
+ layout: {
742
+ 'icon-image': customIconName || 'add_marker_icon',
743
+ 'icon-size': 1,
744
+ 'icon-offset': [4, -19]
745
+ }
746
+ });
747
+
748
+ // 设置地图中心点和缩放级别
749
+ map.setCenter([data.longitude, data.latitude]);
750
+ map.setZoom(data.zoom || mapConfig.maxZoom || 18);
751
+ }
752
+ },
753
+
754
+ /**
755
+ * 添加自定义弹窗到地图
756
+ * @param {Array|Object} lngLat - 经纬度坐标 [lng, lat] 或 { lng, lat }
757
+ * @param {HTMLElement|String} content - 弹窗内容(DOM 元素或 HTML 字符串)
758
+ * @param {String} className - 自定义 CSS 类名,默认 'gis-custom-popup'
759
+ * @param {Array} addOnOffset - 在基础偏移 [37, -107] 上的补充偏移 [dx, dy]
760
+ * @returns {mapboxgl.Popup} popup 实例
761
+ */
762
+ addCustomPopup: function (lngLat, content, className, addOnOffset = [0, 0]) {
763
+ // 移除之前的弹窗
764
+ this.removeCustomPopup()
765
+
766
+ const BASE_OFFSET_X = 37 // 弹窗修饰 SVG 圆点水平偏移
767
+ const BASE_OFFSET_Y = -107 // 弹窗修饰 SVG 圆点垂直偏移
768
+
769
+ const popup = new mapboxgl.Popup({
770
+ closeButton: false,
771
+ closeOnClick: false,
772
+ anchor: 'bottom-left',
773
+ offset: [BASE_OFFSET_X + (addOnOffset[0] || 0), BASE_OFFSET_Y + (addOnOffset[1] || 0)],
774
+ maxWidth: 'none',
775
+ className: className || 'gis-custom-popup'
776
+ })
777
+ .setLngLat(lngLat)
778
+ .setDOMContent(content)
779
+ .addTo(map)
780
+
781
+ this._customPopup = popup
782
+ return popup
783
+ },
784
+
785
+ /**
786
+ * 移除当前自定义弹窗
787
+ */
788
+ removeCustomPopup: function () {
789
+ if (this._customPopup) {
790
+ this._customPopup.remove()
791
+ this._customPopup = null
792
+ }
793
+ },
794
+
795
+
796
+ // ==================== 五、服务URL构建 ====================
797
+
798
+ joinWmtsUrl: function (layerName) {
799
+ return (
800
+ mapConfig.mapUrl +
801
+ "/geoserver/gwc/service/wmts?request=GetTile" +
802
+ "&service=WMTS" +
803
+ "&version=1.0.0" +
804
+ "&layer=" +
805
+ this.workspace +
806
+ ":" +
807
+ layerName +
808
+ "&style=" +
809
+ "&tilematrixset=" +
810
+ this.map_srid +
811
+ "&tilematrix=" +
812
+ this.map_srid +
813
+ ":{z}" +
814
+ "&format=image/png" +
815
+ "&tilecol={x}" +
816
+ "&tilerow={y}"
817
+ );
818
+ },
819
+
820
+
821
+ joinTmsUrl: function (layerName) {
822
+ return (
823
+ mapConfig.mapUrl +
824
+ "/geoserver/gwc/service/tms/1.0.0/" +
825
+ this.workspace +
826
+ ":" +
827
+ layerName +
828
+ "@" +
829
+ this.map_srid +
830
+ "@pbf/{z}/{x}/{y}.pbf"
831
+ );
832
+ },
833
+
834
+
835
+ getTmsUrl: function (z, x, y) {
836
+ const ymax = Math.pow(2, z) - 1;
837
+ const y_tms = ymax - y;
838
+ return mapConfig.mapUrl + `/gis-data/shenzhen/${z}/${x}/${y_tms}.png`;
839
+ },
840
+
841
+ /**
842
+ * 拼接WFS服务地址
843
+ * @param {String} layerName -图层名称
844
+ * @param {String} category -类别(pipeline、manhole等)
845
+ */
846
+ joinWfsUrl(layerName, category = null) {
847
+ let url = mapConfig.mapUrl +
848
+ "/geoserver/" +
849
+ this.workspace +
850
+ "/ows?request=GetFeature" +
851
+ "&service=WFS" +
852
+ "&version=1.1.0" +
853
+ "&typeName=" +
854
+ this.workspace +
855
+ ":" +
856
+ layerName +
857
+ "&outputFormat=application/json" +
858
+ "&srsName=" +
859
+ this.map_srid;
860
+
861
+ if (category) {
862
+ // 全局图层管理器入口
863
+ const layers = LayerConfig.Layers.filter((lc) => {
864
+ return lc.parent === category;
865
+ });
866
+ if (layers.length > 0 &&
867
+ layers[0].fields && layers[0].fields.length > 0) {
868
+ url += "&propertyName=geom,";
869
+ url += layers[0].fields;
870
+ }
871
+ }
872
+
873
+ return url;
874
+ },
875
+
876
+ getWfsQueryUrl: function () {
877
+ return (
878
+ mapConfig.mapUrl + "/geoserver/" + this.workspace +
879
+ "/ows?service=WFS&version=1.0.0" +
880
+ "&request=GetFeature" +
881
+ "&outputFormat=application/json" +
882
+ "&maxFeatures=2500" +
883
+ "&srsName=" + this.map_srid +
884
+ "&typeName="
885
+ );
886
+ },
887
+
888
+
889
+ // ==================== 六、样式与主题切换 ====================
890
+
891
+ setStyle: function (map) {
892
+ if (!map) return;
893
+
894
+ // 独立设置需要的mapbox内置样式
895
+ // 默认的base64 png图片 并进行addImage操作 iVBORw0KGgoAAAANSUhEUgAAAAsAAAArCAYAAABm8CLRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqkld9LAlEUxr93Z3fHXV1bE1JLMoheIh/6B/oHIiilICjohR76A4KgHnroTwh6CIKgICIzKCvNMnVdXd3ZnbnndIcZZ3bWEPoNDnfuOed855tzzz1XGGNgGIbxf8DpdF5omoZer/eXpmmYTCaIRCJot9vwer3wer0wmUwAgFarhXa7jXa7jVarhXa7jU6ng263i16vh36/DwAYDAaIRCKIRCJE0zQMDAzAarWCZVlgjIFSCkopKKXgeR6CICAIAjiOA8dxIIQAQghIkoQkSSBJEkRRhCiKEEURPM+DYRgwDAOGYUBRFCiKAkVRoKoqVFUFpRSapkHzPGiapnnDMAzDMAzDMIzf8M8BXq8XPp8PPp8Poij+9Xg8hkajgXq9jkajgXq9jnq9jmazCUIIGGOglILneQiCAEEQIAgCOI4Dx3EQBAEcxyEQCECWZUiShEAgALvdDovFAovFApvNBovFAkmSIEmSJEnSNVmW/1JV9Zym6XOaptc0TT/QNP1A0/QDTdMPNE0/0DR9T9P0PU3TdzRN39I0fUPT9DVN01c0TV/SNH1B0/Q5TdOnNE2f0DR9TNP0EU3ThzRNH9A0vU/T9B5N07s0Te/SNL1D0/Q2TdNbNE1v0jS9QdP0Ok3TazRNr9I0vULT9DJN00s0TS/SNL1A0/Q8TdNzNE3P0jQ9Q9P0NE3TUzRN/6Rp+jhN00c0TR/SNH1A0/Q+TdN7NE3v0jS9Q9P0Nk3TWzRNb9I0vUHT9DpN02s0Ta/SNL1C0/QyTdNLNE0v0jS9QNP0PE3TczRNz9I0PUMmk0kkEgnE43HE43HE43HEYjFomgZKKSilIIQAAARBAM/zEAQBgiCA53nwPA+e58HzPHiehyAI4DgOHMeB53lwHAeO48BxHHiehyAI4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOPM+D53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB/wD/BGAAuJZK3XZCtKsAAAAASUVORK5CYII=
896
+ // 添加基于base64的自定义图片资源
897
+ if (!map.hasImage('custom_circle_icon')) {
898
+ const img = new Image();
899
+ img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAArCAYAAABm8CLRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqkld9LAlEUxr93Z3fHXV1bE1JLMoheIh/6B/oHIiilICjohR76A4KgHnroTwh6CIKgICIzKCvNMnVdXd3ZnbnndIcZZ3bWEPoNDnfuOed855tzzz1XGGNgGIbxf8DpdF5omoZer/eXpmmYTCaIRCLot9vwer3wer0wmUwAgFarhXa7jXa7jVarhXa7jU6ng263i16vh36/DwAYDAaIRCKIRCJE0zQMDAzAarWCZVlgjIFSCkopKKXgeR6CICAIAjiOA8dxIIQAQghIkoQkSSBJEkRRhCiKEEURPM+DYRgwDAOGYUBRFCiKAkVRoKoqVFUFpRSapkHzPGiapnnDMAzDMIzDMIzf8M8BXq8PPp8PPp8Poij+9Xg8hkajgXq9jkajgXq9jnq9jmazCUIIGGOglILneQiCAEEQIAgCOI4Dx3EQBAEcxyEQCECWZUiShEAgALvdDovFAovFApvNBovFAkmSIEmSJEnSNVmW/1JV9Zym6XOaptc0TT/QNP1A0/QDTdMPNE0/0DR9T9P0PU3TdzRN39I0fUPT9DVN01c0TV/SNH1B0/Q5TdOnNE2f0DR9TNP0EU3ThzRNH9A0vU/T9B5N07s0Te/SNL1D0/Q2TdNbNE1v0jS9QdP0Ok3TazRNr9I0vULT9DJN00s0TS/SNL1A0/Q8TdNzNE3P0jQ9Q9P0NE3TUzRN/6Rp+jhN00c0TR/SNH1A0/Q+TdN7NE3v0jS9Q9P0Nk3TWzRNb9I0vUHT9DpN02s0Ta/SNL1C0/QyTdNLNE0v0jS9QNP0PE3TczRNz9I0PUMmk0kkEgnE43HE43HEYjFomgZKKSilIIQAAARBAM/zEAQBgiCA53nwPA+e58HzPHiehyAI4DgOHMeB53lwHAeO48BxHHiehyAI4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOPM+D53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB/wD/BGAAuJZK3XZCtKsAAAAASUVORK5CYII=';
900
+ img.onload = () => {
901
+ map.addImage('custom_circle_icon', img);
902
+ };
903
+ }
904
+
905
+ // Mapbox GL JS使用不同的样式设置方式
906
+ // 这里可以设置预定义样式或自定义样式
907
+ // map.setStyle('mapbox://styles/mapbox/streets-v11');
908
+ },
909
+
910
+ /**
911
+ * 更改样式
912
+ * @param {String} theme -主题
913
+ */
914
+ changeStyle(theme) {
915
+ if (theme === this._theme) return;
916
+
917
+ this._theme = theme;
918
+ const isDark = this._theme === "dark";
919
+
920
+ // 数据源列表
921
+ const dataSources = this._getSources(isDark ? Dark_Sources : Light_Sources);
922
+ // 基础图层列表
923
+ const baseLayers = isDark ? Dark_Layers : Light_Layers;
924
+
925
+ // 更改样式
926
+ this._changeStyle(dataSources, baseLayers);
927
+ },
928
+
929
+ /**
930
+ * 更改地图样式
931
+ * @param {Object} sources -源对象
932
+ * @param {Array} layers -图层列表
933
+ */
934
+ _changeStyle: function (sources, layers) {
935
+ if (!map) return;
936
+
937
+ const that = this;
938
+
939
+ // 设置样式
940
+ map.setStyle({
941
+ version: 8,
942
+ name: "MaptoMap",
943
+ sprite: this.styleUrl + "/sprite/sprite",
944
+ glyphs: this.styleUrl + "/fonts/{fontstack}/{range}.pbf",
945
+ transition: {
946
+ duration: 300,
947
+ delay: 0,
948
+ },
949
+ sources: sources, // 数据源
950
+ layers: layers, // 图层列表
951
+ });
952
+
953
+ // 样式加载完成事件
954
+ map.on('style.load', () => {
955
+ // 禁止双击缩放
956
+ map.doubleClickZoom.disable();
957
+
958
+ // 自定义样式
959
+ map._params.customStyle = that._theme === "dark"
960
+ ? Dark_Style
961
+ : Light_Style;
962
+ // 获取fill-extrusion类型图层ID
963
+ const mapLayers = map.getStyle().layers;
964
+ for (let i = 0; i < mapLayers.length; i++) {
965
+ if (mapLayers[i].type === 'fill-extrusion') {
966
+ map._params.building3DLayerId = mapLayers[i].id;
967
+ break;
968
+ }
969
+ }
970
+
971
+ // 设置雾
972
+ if (that.withFog) {
973
+ that._setFog();
974
+ }
975
+ // 设置地形
976
+ if (that.withDem) {
977
+ that._loadDEM();
978
+ }
979
+
980
+ // 触发地图更改完成事件
981
+ that.$emit("changed", map);
982
+ });
983
+ },
984
+
985
+ setLayoutProperty: function (layerId, propertyName, propertyValue) {
986
+ if (!map) return;
987
+ map.setLayoutProperty(layerId, propertyName, propertyValue);
988
+ },
989
+
990
+ setPaintProperty: function (layerId, propertyName, propertyValue) {
991
+ if (!map) return;
992
+ map.setPaintProperty(layerId, propertyName, propertyValue);
993
+ },
994
+
995
+ setFog: function () {
996
+ this._setFog();
997
+ },
998
+
999
+ /**
1000
+ * 设置雾
1001
+ */
1002
+ _setFog: function () {
1003
+ if (!map) return;
1004
+ if (this._theme === "dark") {
1005
+ map.setFog({
1006
+ 'range': [1, 20],
1007
+ 'color': '#F8F8FF',
1008
+ 'high-color': '#ADD8E6',
1009
+ 'space-color': '#0B1026',
1010
+ 'horizon-blend': 0.001,
1011
+ 'star-intensity': 0.01
1012
+ });
1013
+ } else {
1014
+ map.setFog({
1015
+ 'range': [0, 20],
1016
+ 'color': '#FFFFFF',
1017
+ 'high-color': '#ADD8E6',
1018
+ 'space-color': '#d8f2ff',
1019
+ 'horizon-blend': 0.005,
1020
+ 'star-intensity': 0
1021
+ });
1022
+ }
1023
+ },
1024
+
1025
+ setDEM: function (hillshade = false) {
1026
+ this._loadDEM(hillshade);
1027
+ },
1028
+
1029
+ /**
1030
+ * 加载DEM
1031
+ * @param {Boolean} hillshade -是否加载山体阴影
1032
+ */
1033
+ _loadDEM: function (hillshade = false) {
1034
+ if (!map) return;
1035
+
1036
+ let demSourceId = this._demSourceId;
1037
+ let minZoom = this.demMinZoom;
1038
+ let maxZoom = this.demMaxZoom;
1039
+
1040
+ if (demSourceId) {
1041
+ // 获取离线DEM数据源
1042
+ const demSource = map.getSource(demSourceId);
1043
+ if (demSource) {
1044
+ minZoom = demSource.minzoom;
1045
+ maxZoom = demSource.maxzoom;
1046
+ }
1047
+ } else {
1048
+ demSourceId = 'mapbox-dem';
1049
+ if (!map.getSource(demSourceId)) {
1050
+ // 加载在线DEM
1051
+ map.addSource(demSourceId, {
1052
+ type: 'raster-dem',
1053
+ url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
1054
+ tileSize: 256,
1055
+ minzoom: minZoom,
1056
+ maxzoom: maxZoom
1057
+ });
1058
+ }
1059
+ }
1060
+ // 设置地形
1061
+ map.setTerrain({
1062
+ source: demSourceId,
1063
+ exaggeration: 1.0
1064
+ });
1065
+
1066
+ // 山体阴影
1067
+ if (hillshade && hillshade === true) {
1068
+ const hillshadeSourceId = demSourceId;
1069
+ const hillshadeLayerId = demSourceId + '-hillshading';
1070
+ if (!map.getLayer(hillshadeLayerId)) {
1071
+ // 加载hillshade图层
1072
+ map.addLayer({
1073
+ type: 'hillshade',
1074
+ id: hillshadeLayerId,
1075
+ source: hillshadeSourceId,
1076
+ minzoom: minZoom,
1077
+ maxzoom: maxZoom,
1078
+ paint: {
1079
+ 'hillshade-exaggeration': 1.0,
1080
+ 'hillshade-highlight-color': this._theme === 'dark' ? '#7387B9' : '#FFFFFF',
1081
+ 'hillshade-shadow-color': this._theme === 'dark' ? '#000615' : '#333333',
1082
+ }
1083
+ });
1084
+ }
1085
+ }
1086
+ },
1087
+
1088
+ /**
1089
+ * 设置地图缩放级别和中心点
1090
+ */
1091
+ setZoom: function (map, points, zoomLevel = null) {
1092
+ if (!map || !points || points.length === 0) return;
1093
+
1094
+ let coordinates;
1095
+ if (typeof points[0] === 'number' && points.length % 2 === 0) {
1096
+ // 处理扁平数组格式
1097
+ coordinates = [];
1098
+ for (let i = 0; i < points.length; i += 2) {
1099
+ coordinates.push([points[i], points[i + 1]]);
1100
+ }
1101
+ } else {
1102
+ // 处理对象数组格式
1103
+ coordinates = points.map(p => [p.longitude, p.latitude]);
1104
+ }
1105
+
1106
+ // 计算所有坐标的边界框
1107
+ const bounds = coordinates.reduce(
1108
+ (bbox, coord) => {
1109
+ return [
1110
+ Math.min(bbox[0], coord[0]), // 最小经度
1111
+ Math.min(bbox[1], coord[1]), // 最小纬度
1112
+ Math.max(bbox[2], coord[0]), // 最大经度
1113
+ Math.max(bbox[3], coord[1]) // 最大纬度
1114
+ ];
1115
+ },
1116
+ [Infinity, Infinity, -Infinity, -Infinity] // 初始边界
1117
+ );
1118
+
1119
+ if (zoomLevel) {
1120
+ const center = [
1121
+ (bounds[0] + bounds[2]) / 2,
1122
+ (bounds[1] + bounds[3]) / 2
1123
+ ];
1124
+ map.setCenter(center);
1125
+ map.setZoom(zoomLevel);
1126
+ } else {
1127
+ map.fitBounds(
1128
+ [[bounds[0], bounds[1]], [bounds[2], bounds[3]]],
1129
+ {
1130
+ padding: 80,
1131
+ maxZoom: 16,
1132
+ duration: 800
1133
+ }
1134
+ );
1135
+ }
1136
+ },
1137
+
1138
+
1139
+ // ==================== 七、巡检业务绘制 ====================
1140
+
1141
+ drawPatrolTask: function (map, data) {
1142
+ if (!map || !data) return;
1143
+
1144
+ const points = data.patrolPointDetailDTOs || [];
1145
+ const lines = data.patrolTaskPlanPaths || [];
1146
+
1147
+ if (!points.length || !lines.length) return;
1148
+
1149
+ this.setZoom(map, points);
1150
+
1151
+ // 清除之前的图层
1152
+ if (map.getLayer('patrol-points')) map.removeLayer('patrol-points');
1153
+ if (map.getSource('patrol-points')) map.removeSource('patrol-points');
1154
+ if (map.getLayer('patrol-lines')) map.removeLayer('patrol-lines');
1155
+ if (map.getSource('patrol-lines')) map.removeSource('patrol-lines');
1156
+
1157
+ // 添加点数据
1158
+ const pointFeatures = points.map(po => ({
1159
+ type: 'Feature',
1160
+ geometry: {
1161
+ type: 'Point',
1162
+ coordinates: [po.longitude, po.latitude]
1163
+ },
1164
+ properties: {
1165
+ ...po
1166
+ }
1167
+ }));
1168
+
1169
+ map.addSource('patrol-points', {
1170
+ type: 'geojson',
1171
+ data: {
1172
+ type: 'FeatureCollection',
1173
+ features: pointFeatures
1174
+ }
1175
+ });
1176
+
1177
+ // 根据状态设置不同图标
1178
+ map.addLayer({
1179
+ id: 'patrol-points',
1180
+ type: 'circle',
1181
+ source: 'patrol-points',
1182
+ paint: {
1183
+ 'circle-radius': 6,
1184
+ 'circle-color': [
1185
+ 'match',
1186
+ ['get', 'status'],
1187
+ '正常', '#7ed321',
1188
+ '异常', '#ff0000',
1189
+ '未检', '#9b9b9b',
1190
+ '#3a6bdb' // 默认颜色
1191
+ ],
1192
+ 'circle-stroke-width': 2,
1193
+ 'circle-stroke-color': '#ffffff'
1194
+ }
1195
+ });
1196
+
1197
+ // 添加点标签
1198
+ map.addLayer({
1199
+ id: 'patrol-point-labels',
1200
+ type: 'symbol',
1201
+ source: 'patrol-points',
1202
+ layout: {
1203
+ 'text-field': ['get', 'patrolPoint'],
1204
+ 'text-offset': [0, 1.5],
1205
+ 'text-anchor': 'top'
1206
+ },
1207
+ paint: {
1208
+ 'text-color': '#0093ff'
1209
+ }
1210
+ });
1211
+
1212
+ // 添加线数据
1213
+ if (lines.length >= 2) {
1214
+ const lineFeatures = [];
1215
+ for (let i = 0; i < lines.length - 1; i++) {
1216
+ lineFeatures.push({
1217
+ type: 'Feature',
1218
+ geometry: {
1219
+ type: 'LineString',
1220
+ coordinates: [
1221
+ [lines[i].longitude, lines[i].latitude],
1222
+ [lines[i + 1].longitude, lines[i + 1].latitude]
1223
+ ]
1224
+ },
1225
+ properties: {
1226
+ validate: lines[i].validate
1227
+ }
1228
+ });
1229
+ }
1230
+
1231
+ map.addSource('patrol-lines', {
1232
+ type: 'geojson',
1233
+ data: {
1234
+ type: 'FeatureCollection',
1235
+ features: lineFeatures
1236
+ }
1237
+ });
1238
+
1239
+ map.addLayer({
1240
+ id: 'patrol-lines',
1241
+ type: 'line',
1242
+ source: 'patrol-lines',
1243
+ paint: {
1244
+ 'line-color': [
1245
+ 'match',
1246
+ ['get', 'validate'],
1247
+ 'valid', plan_color_valid,
1248
+ plan_color_invalid
1249
+ ],
1250
+ 'line-width': 4
1251
+ }
1252
+ });
1253
+ }
1254
+ },
1255
+
1256
+
1257
+ drawPatrol: function (map, data, pointField) {
1258
+ if (!map || !data) return;
1259
+ const taskUniqueId = data.id || data.patrolTaskId;
1260
+ if (!taskUniqueId) return;
1261
+
1262
+ const points = data.patrolTaskPointTrackDTOs || [];
1263
+ const lines = data.patrolTaskPlanPaths || [];
1264
+ if (!points.length || !lines.length) return;
1265
+
1266
+ this.setZoom(map, points);
1267
+
1268
+ // 定义动态唯一ID
1269
+ const pointSourceId = `patrol-track-points-${taskUniqueId}`;
1270
+ const pointIconLayerId = `patrol-track-points-icons-${taskUniqueId}`;
1271
+ const pointLabelLayerId = `patrol-track-point-labels-${taskUniqueId}`;
1272
+ const lineSourceId = `patrol-track-lines-${taskUniqueId}`;
1273
+ const lineLayerId = `patrol-track-lines-${taskUniqueId}`;
1274
+
1275
+ // 清除旧图层/数据源(使用动态ID)
1276
+ if (map.getLayer(pointIconLayerId)) map.removeLayer(pointIconLayerId);
1277
+ if (map.getLayer(pointLabelLayerId)) map.removeLayer(pointLabelLayerId);
1278
+ if (map.getSource(pointSourceId)) map.removeSource(pointSourceId);
1279
+ if (map.getLayer(lineLayerId)) map.removeLayer(lineLayerId);
1280
+ if (map.getSource(lineSourceId)) map.removeSource(lineSourceId);
1281
+
1282
+ // 添加点数据
1283
+ const pointFeatures = points.map(po => ({
1284
+ type: 'Feature',
1285
+ geometry: {
1286
+ type: 'Point',
1287
+ coordinates: [po.longitude, po.latitude]
1288
+ },
1289
+ properties: {
1290
+ ...po
1291
+ }
1292
+ }));
1293
+
1294
+ // 在 addSource 中添加图标属性
1295
+ map.addSource(pointSourceId, {
1296
+ type: 'geojson',
1297
+ data: {
1298
+ type: 'FeatureCollection',
1299
+ features: pointFeatures.map(feature => {
1300
+ let icon;
1301
+ const status = feature.properties.status;
1302
+ switch (status) {
1303
+ case '正常':
1304
+ icon = 'img_done';
1305
+ break;
1306
+ case '异常':
1307
+ icon = 'img_error';
1308
+ break;
1309
+ case '未检':
1310
+ icon = 'img_invalid';
1311
+ break;
1312
+ default:
1313
+ icon = 'img_todo';
1314
+ break;
1315
+ }
1316
+ return {
1317
+ ...feature,
1318
+ properties: {...feature.properties, icon: icon}
1319
+ };
1320
+ })
1321
+ }
1322
+ });
1323
+
1324
+ // 在图层中使用图标
1325
+ map.addLayer({
1326
+ id: pointIconLayerId,
1327
+ type: 'symbol',
1328
+ source: pointSourceId,
1329
+ layout: {
1330
+ 'icon-image': ['get', 'icon'],
1331
+ 'icon-size': 1,
1332
+ 'icon-anchor': 'bottom'
1333
+ }
1334
+ });
1335
+
1336
+ // 添加点标签
1337
+ map.addLayer({
1338
+ id: pointLabelLayerId,
1339
+ type: 'symbol',
1340
+ source: pointSourceId,
1341
+ layout: {
1342
+ 'text-field': ['get', 'patrolPointName'],
1343
+ 'text-offset': [0, 1.5],
1344
+ 'text-anchor': 'top'
1345
+ },
1346
+ paint: {'text-color': '#0093ff'}
1347
+ });
1348
+
1349
+ // 添加线数据,绑定任务信息到 properties
1350
+ if (lines.length >= 2) {
1351
+ const lineFeatures = [];
1352
+ for (let i = 0; i < lines.length - 1; i++) {
1353
+ lineFeatures.push({
1354
+ type: 'Feature',
1355
+ geometry: {
1356
+ type: 'LineString',
1357
+ coordinates: [
1358
+ [lines[i].longitude, lines[i].latitude],
1359
+ [lines[i + 1].longitude, lines[i + 1].latitude]
1360
+ ]
1361
+ },
1362
+ properties: {
1363
+ validate: lines[i].validate,
1364
+ taskId: taskUniqueId,
1365
+ taskInfo: {
1366
+ name: data.name,
1367
+ executeStatus: data.executeStatus,
1368
+ startTime: data.startTime,
1369
+ endTime: data.endTime,
1370
+ faultCount: data.faultCount,
1371
+ patrolPointCount: data.patrolPointCount,
1372
+ inspectedCount: data.inspectedCount,
1373
+ planPathLength: data.planPathLength,
1374
+ validPathLength: data.validPathLength
1375
+ }
1376
+ }
1377
+ });
1378
+ }
1379
+
1380
+ map.addSource(lineSourceId, {
1381
+ type: 'geojson',
1382
+ data: {type: 'FeatureCollection', features: lineFeatures}
1383
+ });
1384
+
1385
+ map.addLayer({
1386
+ id: lineLayerId,
1387
+ type: 'line',
1388
+ source: lineSourceId,
1389
+ paint: {
1390
+ 'line-color': ['match', ['get', 'validate'], 'valid', plan_color_valid, plan_color_invalid],
1391
+ 'line-width': 4,
1392
+ 'line-dasharray': [2, 2]
1393
+ },
1394
+ interactive: true // 开启线图层点击交互
1395
+ });
1396
+ }
1397
+
1398
+ // console.log('当前地图图层ID列表:', map.getStyle().layers.map(layer => layer.id));
1399
+ },
1400
+
1401
+
1402
+ drawPatrolTaskInGaoDe: function (map, data) {
1403
+ if (!map || !data) return;
1404
+
1405
+ const points = data.patrolPointDetailDTOs || [];
1406
+ const lines = data.patrolTaskPlanPaths || [];
1407
+
1408
+ if (!points.length || !lines.length) return;
1409
+
1410
+ this.setZoom(map, points);
1411
+
1412
+ // 清除之前的图层
1413
+ if (map.getLayer('patrol-points')) map.removeLayer('patrol-points');
1414
+ if (map.getSource('patrol-points')) map.removeSource('patrol-points');
1415
+ if (map.getLayer('patrol-lines')) map.removeLayer('patrol-lines');
1416
+ if (map.getSource('patrol-lines')) map.removeSource('patrol-lines');
1417
+
1418
+ // 添加点数据
1419
+ // 返回高德结果时需要进行wgs84转gcj02
1420
+ points.forEach(po => {
1421
+ [po.longitude, po.latitude] = SpatialRefUtils.wgs84toGcj02([po.longitude, po.latitude])
1422
+ })
1423
+ const pointFeatures = points.map(po => ({
1424
+ type: 'Feature',
1425
+ geometry: {
1426
+ type: 'Point',
1427
+ coordinates: [po.longitude, po.latitude]
1428
+ },
1429
+ properties: {
1430
+ ...po
1431
+ }
1432
+ }));
1433
+
1434
+ map.addSource('patrol-points', {
1435
+ type: 'geojson',
1436
+ data: {
1437
+ type: 'FeatureCollection',
1438
+ features: pointFeatures
1439
+ }
1440
+ });
1441
+
1442
+ // 根据状态设置不同图标
1443
+ map.addLayer({
1444
+ id: 'patrol-points',
1445
+ type: 'circle',
1446
+ source: 'patrol-points',
1447
+ paint: {
1448
+ 'circle-radius': 6,
1449
+ 'circle-color': [
1450
+ 'match',
1451
+ ['get', 'status'],
1452
+ '正常', '#7ed321',
1453
+ '异常', '#ff0000',
1454
+ '未检', '#9b9b9b',
1455
+ '#3a6bdb' // 默认颜色
1456
+ ],
1457
+ 'circle-stroke-width': 2,
1458
+ 'circle-stroke-color': '#ffffff'
1459
+ }
1460
+ });
1461
+
1462
+ // 添加点标签
1463
+ map.addLayer({
1464
+ id: 'patrol-point-labels',
1465
+ type: 'symbol',
1466
+ source: 'patrol-points',
1467
+ layout: {
1468
+ 'text-field': ['get', 'patrolPoint'],
1469
+ 'text-offset': [0, 1.5],
1470
+ 'text-anchor': 'top'
1471
+ },
1472
+ paint: {
1473
+ 'text-color': '#0093ff'
1474
+ }
1475
+ });
1476
+
1477
+ // 添加线数据
1478
+ if (lines.length >= 2) {
1479
+ const lineFeatures = [];
1480
+ for (let i = 0; i < lines.length - 1; i++) {
1481
+ lineFeatures.push({
1482
+ type: 'Feature',
1483
+ geometry: {
1484
+ type: 'LineString',
1485
+ coordinates: [
1486
+ [lines[i].longitude, lines[i].latitude],
1487
+ [lines[i + 1].longitude, lines[i + 1].latitude]
1488
+ ]
1489
+ },
1490
+ properties: {
1491
+ validate: lines[i].validate
1492
+ }
1493
+ });
1494
+ }
1495
+
1496
+ map.addSource('patrol-lines', {
1497
+ type: 'geojson',
1498
+ data: {
1499
+ type: 'FeatureCollection',
1500
+ features: lineFeatures
1501
+ }
1502
+ });
1503
+
1504
+ map.addLayer({
1505
+ id: 'patrol-lines',
1506
+ type: 'line',
1507
+ source: 'patrol-lines',
1508
+ paint: {
1509
+ 'line-color': [
1510
+ 'match',
1511
+ ['get', 'validate'],
1512
+ 'valid', plan_color_valid,
1513
+ plan_color_invalid
1514
+ ],
1515
+ 'line-width': 4
1516
+ }
1517
+ });
1518
+ }
1519
+ },
1520
+
1521
+
1522
+ drawPatrolInGaoDe: function (map, data, pointField) {
1523
+ if (!map || !data) return;
1524
+ const taskUniqueId = data.id || data.patrolTaskId;
1525
+ if (!taskUniqueId) return;
1526
+
1527
+ const points = data.patrolTaskPointTrackDTOs || [];
1528
+ const lines = data.patrolTaskPlanPaths || [];
1529
+ if (!points.length || !lines.length) return;
1530
+
1531
+ this.setZoom(map, points);
1532
+
1533
+ // 定义动态唯一ID
1534
+ const pointSourceId = `patrol-track-points-${taskUniqueId}`;
1535
+ const pointIconLayerId = `patrol-track-points-icons-${taskUniqueId}`;
1536
+ const pointLabelLayerId = `patrol-track-point-labels-${taskUniqueId}`;
1537
+ const lineSourceId = `patrol-track-lines-${taskUniqueId}`;
1538
+ const lineLayerId = `patrol-track-lines-${taskUniqueId}`;
1539
+
1540
+ // 清除旧图层/数据源(使用动态ID)
1541
+ if (map.getLayer(pointIconLayerId)) map.removeLayer(pointIconLayerId);
1542
+ if (map.getLayer(pointLabelLayerId)) map.removeLayer(pointLabelLayerId);
1543
+ if (map.getSource(pointSourceId)) map.removeSource(pointSourceId);
1544
+ if (map.getLayer(lineLayerId)) map.removeLayer(lineLayerId);
1545
+ if (map.getSource(lineSourceId)) map.removeSource(lineSourceId);
1546
+
1547
+ // 添加点数据
1548
+ // 返回高德结果时需要进行wgs84转gcj02
1549
+ points.forEach(po => {
1550
+ [po.longitude, po.latitude] = SpatialRefUtils.wgs84toGcj02([po.longitude, po.latitude])
1551
+ })
1552
+ const pointFeatures = points.map(po => ({
1553
+ type: 'Feature',
1554
+ geometry: {
1555
+ type: 'Point',
1556
+ coordinates: [po.longitude, po.latitude]
1557
+ },
1558
+ properties: {
1559
+ ...po
1560
+ }
1561
+ }));
1562
+
1563
+ // 在 addSource 中添加图标属性
1564
+ map.addSource(pointSourceId, {
1565
+ type: 'geojson',
1566
+ data: {
1567
+ type: 'FeatureCollection',
1568
+ features: pointFeatures.map(feature => {
1569
+ let icon;
1570
+ const status = feature.properties.status;
1571
+ switch (status) {
1572
+ case '正常':
1573
+ icon = 'img_done';
1574
+ break;
1575
+ case '异常':
1576
+ icon = 'img_error';
1577
+ break;
1578
+ case '未检':
1579
+ icon = 'img_invalid';
1580
+ break;
1581
+ default:
1582
+ icon = 'img_todo';
1583
+ break;
1584
+ }
1585
+ return {
1586
+ ...feature,
1587
+ properties: {...feature.properties, icon: icon}
1588
+ };
1589
+ })
1590
+ }
1591
+ });
1592
+
1593
+ // 在图层中使用图标
1594
+ map.addLayer({
1595
+ id: pointIconLayerId,
1596
+ type: 'symbol',
1597
+ source: pointSourceId,
1598
+ layout: {
1599
+ 'icon-image': ['get', 'icon'],
1600
+ 'icon-size': 1,
1601
+ 'icon-anchor': 'bottom'
1602
+ }
1603
+ });
1604
+
1605
+ // 添加点标签
1606
+ map.addLayer({
1607
+ id: pointLabelLayerId,
1608
+ type: 'symbol',
1609
+ source: pointSourceId,
1610
+ layout: {
1611
+ 'text-field': ['get', 'patrolPointName'],
1612
+ 'text-offset': [0, 1.5],
1613
+ 'text-anchor': 'top'
1614
+ },
1615
+ paint: {'text-color': '#0093ff'}
1616
+ });
1617
+
1618
+ // 添加线数据,绑定任务信息到 properties
1619
+ if (lines.length >= 2) {
1620
+ const lineFeatures = [];
1621
+ for (let i = 0; i < lines.length - 1; i++) {
1622
+ lineFeatures.push({
1623
+ type: 'Feature',
1624
+ geometry: {
1625
+ type: 'LineString',
1626
+ coordinates: [
1627
+ [lines[i].longitude, lines[i].latitude],
1628
+ [lines[i + 1].longitude, lines[i + 1].latitude]
1629
+ ]
1630
+ },
1631
+ properties: {
1632
+ validate: lines[i].validate,
1633
+ taskId: taskUniqueId,
1634
+ taskInfo: {
1635
+ name: data.name,
1636
+ executeStatus: data.executeStatus,
1637
+ startTime: data.startTime,
1638
+ endTime: data.endTime,
1639
+ faultCount: data.faultCount,
1640
+ patrolPointCount: data.patrolPointCount,
1641
+ inspectedCount: data.inspectedCount,
1642
+ planPathLength: data.planPathLength,
1643
+ validPathLength: data.validPathLength
1644
+ }
1645
+ }
1646
+ });
1647
+ }
1648
+
1649
+ map.addSource(lineSourceId, {
1650
+ type: 'geojson',
1651
+ data: {type: 'FeatureCollection', features: lineFeatures}
1652
+ });
1653
+
1654
+ map.addLayer({
1655
+ id: lineLayerId,
1656
+ type: 'line',
1657
+ source: lineSourceId,
1658
+ paint: {
1659
+ 'line-color': ['match', ['get', 'validate'], 'valid', plan_color_valid, plan_color_invalid],
1660
+ 'line-width': 4,
1661
+ 'line-dasharray': [2, 2]
1662
+ },
1663
+ interactive: true // 开启线图层点击交互
1664
+ });
1665
+ }
1666
+
1667
+ // console.log('当前地图图层ID列表:', map.getStyle().layers.map(layer => layer.id));
1668
+ },
1669
+
1670
+ /**
1671
+ * 定位到当前位置
1672
+ */
1673
+ placePoint: function (map, location, callback) {
1674
+ if (!map) return;
1675
+ if (Array.isArray(location) && location.length === 2) {
1676
+ map.setCenter(location)
1677
+ map.setZoom(mapConfig.zoom);
1678
+ } else {
1679
+ navigator.geolocation.getCurrentPosition(
1680
+ (position) => {
1681
+ console.log('navigator.geolocation', position);
1682
+ const point = {
1683
+ lng: position.coords.longitude,
1684
+ lat: position.coords.latitude
1685
+ };
1686
+
1687
+ map.setCenter([point.lng, point.lat]);
1688
+ map.setZoom(mapConfig.maxZoom);
1689
+ callback && callback(point);
1690
+ },
1691
+ (error) => {
1692
+ switch (error.code) {
1693
+ case error.PERMISSION_DENIED:
1694
+ console.error("用户拒绝了位置请求");
1695
+ break;
1696
+ case error.POSITION_UNAVAILABLE:
1697
+ console.error("位置信息不可用");
1698
+ break;
1699
+ case error.TIMEOUT:
1700
+ console.error("请求超时");
1701
+ break;
1702
+ default:
1703
+ console.error("未知错误", error.message);
1704
+ }
1705
+ // 默认定位到地图中心点
1706
+ const point = {lng: mapConfig.center[0], lat: mapConfig.center[1]};
1707
+ map.setCenter([point.lng, point.lat]);
1708
+ map.setZoom(mapConfig.maxZoom);
1709
+ callback && callback(point);
1710
+ },
1711
+ {
1712
+ enableHighAccuracy: true, // 高精度(可能更耗电)
1713
+ timeout: 10000, // 10秒超时
1714
+ maximumAge: 30000 // 允许使用30秒内的缓存位置
1715
+ }
1716
+ );
1717
+ }
1718
+ },
1719
+
1720
+ // ==================== 八、地图交互与搜索(POI) ====================
1721
+
1722
+ /**
1723
+ * 添加搜索功能
1724
+ * @param {string} containerId - 搜索输入框的容器ID
1725
+ * @param {Array} bounds - 搜索边界范围
1726
+ * @param {Function} callback - 回调函数
1727
+ */
1728
+ addSearch(containerId, bounds = [], callback) {
1729
+ // 检查容器ID是否存在
1730
+ if (!containerId) return;
1731
+
1732
+ // 通过容器ID获取输入框元素
1733
+ const inputElement = document.getElementById(containerId);
1734
+ inputElement.setAttribute('placeholder', '请输入搜索内容并通过↩︎进行查询')
1735
+ if (!inputElement) {
1736
+ console.error(`未找到ID为 ${containerId} 的输入框元素`);
1737
+ return;
1738
+ }
1739
+
1740
+ // 创建搜索结果容器并插入到输入框下方
1741
+ let resultListContainer = document.getElementById(`${containerId}-results`);
1742
+ if (!resultListContainer) {
1743
+ resultListContainer = document.createElement('div');
1744
+ resultListContainer.id = `${containerId}-results`;
1745
+ resultListContainer.className = 'search-results-container';
1746
+ inputElement.parentNode.insertBefore(resultListContainer, inputElement.nextSibling);
1747
+ }
1748
+
1749
+ // 默认隐藏搜索结果容器
1750
+ resultListContainer.style.display = 'none';
1751
+
1752
+ // 监听输入事件,当输入为空时清空并隐藏结果列表
1753
+ inputElement.addEventListener('input', (event) => {
1754
+ const keyword = event.target.value.trim();
1755
+ if (!keyword) {
1756
+ // 清空并隐藏搜索结果列表
1757
+ this.clearSearchResults(containerId);
1758
+ }
1759
+ });
1760
+
1761
+ inputElement.addEventListener('keydown', (event) => {
1762
+ if (event.key === 'Enter') {
1763
+ event.preventDefault();
1764
+ const keyword = inputElement.value.trim();
1765
+ if (keyword) {
1766
+ this.executeSearch(containerId, bounds, (poiList) => {
1767
+ // 展示搜索结果列表
1768
+ this.showSearchResults(containerId, poiList);
1769
+ callback && callback(poiList);
1770
+ });
1771
+ } else {
1772
+ // 如果输入为空,清空并隐藏结果列表
1773
+ this.clearSearchResults(containerId);
1774
+ }
1775
+ }
1776
+ });
1777
+
1778
+ // 添加输入框失去焦点时隐藏结果列表的事件
1779
+ inputElement.addEventListener('blur', () => {
1780
+ // 延迟隐藏,确保点击列表项时不会立即隐藏
1781
+ setTimeout(() => {
1782
+ if (resultListContainer) {
1783
+ resultListContainer.style.display = 'none';
1784
+ }
1785
+ }, 200);
1786
+ });
1787
+
1788
+ // 添加输入框获得焦点时显示结果列表的事件(如果有结果)
1789
+ inputElement.addEventListener('focus', () => {
1790
+ if (resultListContainer && resultListContainer.children.length > 0) {
1791
+ resultListContainer.style.display = 'block';
1792
+ }
1793
+ });
1794
+ },
1795
+
1796
+ executeSearch(containerId, bounds = [], callback) {
1797
+ // 通过容器ID获取输入框元素
1798
+ const inputElement = document.getElementById(containerId);
1799
+ if (!inputElement) {
1800
+ console.error(`未找到ID为 ${containerId} 的输入框元素`);
1801
+ return;
1802
+ }
1803
+ // 获取输入框的值作为搜索关键词
1804
+ const keyword = inputElement.value.trim();
1805
+ if (!keyword) return;
1806
+
1807
+ // 天地图POI搜索API URL (使用注释中的v2/search接口)
1808
+ const baseUrl = 'https://api.tianditu.gov.cn/v2/search';
1809
+
1810
+ // 构建请求参数 (按照注释中的格式)
1811
+ const postStr = {
1812
+ keyWord: keyword,
1813
+ level: 12,
1814
+ queryType: 1,
1815
+ start: 0,
1816
+ count: 100
1817
+ };
1818
+
1819
+ // 如果提供了搜索范围,则添加边界参数
1820
+ if (bounds && bounds.length === 4) {
1821
+ postStr.mapBound = `${bounds[0]},${bounds[1]},${bounds[2]},${bounds[3]}`;
1822
+ } else {
1823
+ postStr.mapBound = `${mapConfig.mapExtent[0]},${mapConfig.mapExtent[1]},${mapConfig.mapExtent[2]},${mapConfig.mapExtent[3]}`;
1824
+ }
1825
+
1826
+ // 构建完整的请求URL
1827
+ const params = new URLSearchParams({
1828
+ postStr: JSON.stringify(postStr),
1829
+ type: 'query',
1830
+ tk: TokenUtils.TDT_token
1831
+ });
1832
+
1833
+ // 发送请求
1834
+ fetch(`${baseUrl}?${params.toString()}`)
1835
+ .then(response => response.json())
1836
+ .then(data => {
1837
+ if (data.pois) {
1838
+ // 处理返回的数据,转换为统一格式
1839
+ const poiList = data.pois.map(item => ({
1840
+ id: item.lonlat ? item.lonlat.split(',')[1] : '', // 使用lonlat生成ID
1841
+ name: item.name,
1842
+ address: item.address || '',
1843
+ longitude: item.lonlat ? parseFloat(item.lonlat.split(',')[0]) : 0,
1844
+ latitude: item.lonlat ? parseFloat(item.lonlat.split(',')[1]) : 0,
1845
+ tel: item.phone || '',
1846
+ type: item.type || ''
1847
+ }));
1848
+
1849
+ // 使用Mapbox绘制POI结果
1850
+ this.drawPOIResults(poiList);
1851
+
1852
+ callback && callback(poiList);
1853
+ } else {
1854
+ this.clearPOIResults();
1855
+ callback && callback([]);
1856
+ }
1857
+ })
1858
+ .catch(error => {
1859
+ console.error('天地图POI搜索失败:', error);
1860
+ this.clearPOIResults();
1861
+ callback && callback([]);
1862
+ });
1863
+ },
1864
+
1865
+ drawPOIResults: function (poiList) {
1866
+ if (!map || !poiList || !poiList.length) return;
1867
+
1868
+ // 清除之前的结果图层
1869
+ this.clearPOIResults();
1870
+
1871
+ // 创建GeoJSON数据
1872
+ const geojson = {
1873
+ type: 'FeatureCollection',
1874
+ features: poiList.map(poi => ({
1875
+ type: 'Feature',
1876
+ geometry: {
1877
+ type: 'Point',
1878
+ coordinates: [poi.longitude, poi.latitude]
1879
+ },
1880
+ properties: {
1881
+ id: poi.id,
1882
+ name: poi.name,
1883
+ address: poi.address,
1884
+ tel: poi.tel,
1885
+ type: poi.type
1886
+ }
1887
+ }))
1888
+ };
1889
+
1890
+ // 添加数据源
1891
+ map.addSource('poi-results', {
1892
+ type: 'geojson',
1893
+ data: geojson
1894
+ });
1895
+
1896
+ // 添加点图层
1897
+ map.addLayer({
1898
+ id: 'poi-results',
1899
+ type: 'circle',
1900
+ source: 'poi-results',
1901
+ paint: {
1902
+ 'circle-radius': 8,
1903
+ 'circle-color': '#ff6b35',
1904
+ 'circle-stroke-width': 2,
1905
+ 'circle-stroke-color': '#ffffff'
1906
+ }
1907
+ });
1908
+
1909
+ // 添加标签图层
1910
+ map.addLayer({
1911
+ id: 'poi-labels',
1912
+ type: 'symbol',
1913
+ source: 'poi-results',
1914
+ layout: {
1915
+ 'text-field': ['get', 'name'],
1916
+ 'text-offset': [0, 1.5],
1917
+ 'text-anchor': 'top',
1918
+ 'text-size': 12
1919
+ },
1920
+ paint: {
1921
+ 'text-color': '#333333',
1922
+ 'text-halo-color': '#ffffff',
1923
+ 'text-halo-width': 1
1924
+ }
1925
+ });
1926
+
1927
+ // 添加点击事件
1928
+ map.on('click', 'poi-results', (e) => {
1929
+ const feature = e.features[0];
1930
+ new mapboxgl.Popup({offset: [0, -15]})
1931
+ .setLngLat(feature.geometry.coordinates)
1932
+ .setHTML(` <div style="padding: 10px;">
1933
+ <h3 style="margin: 0 0 5px 0;">${feature.properties.name}</h3>
1934
+ <p style="margin: 5px 0;"><strong>地址:</strong> ${feature.properties.address || '无'}</p>
1935
+ <p style="margin: 5px 0;"><strong>电话:</strong> ${feature.properties.tel || '无'}</p>
1936
+ <p style="margin: 5px 0;"><strong>类型:</strong> ${feature.properties.type || '未知'}</p>
1937
+ </div>
1938
+ `)
1939
+ .addTo(map);
1940
+ });
1941
+
1942
+ // 设置鼠标悬停效果
1943
+ map.on('mouseenter', 'poi-results', () => {
1944
+ map.getCanvas().style.cursor = 'pointer';
1945
+ });
1946
+
1947
+ map.on('mouseleave', 'poi-results', () => {
1948
+ map.getCanvas().style.cursor = '';
1949
+ });
1950
+ },
1951
+
1952
+
1953
+ clearPOIResults: function () {
1954
+ if (!map) return;
1955
+
1956
+ if (map.getLayer('poi-results')) {
1957
+ map.removeLayer('poi-results');
1958
+ }
1959
+ if (map.getLayer('poi-labels')) {
1960
+ map.removeLayer('poi-labels');
1961
+ }
1962
+ if (map.getSource('poi-results')) {
1963
+ map.removeSource('poi-results');
1964
+ }
1965
+
1966
+ // 移除事件监听器
1967
+ map.off('click', 'poi-results');
1968
+ map.off('mouseenter', 'poi-results');
1969
+ map.off('mouseleave', 'poi-results');
1970
+ },
1971
+
1972
+ /**
1973
+ * 展示搜索结果列表
1974
+ * @param {string} containerId - 搜索输入框的容器ID
1975
+ * @param {Array} poiList - POI结果列表
1976
+ */
1977
+ showSearchResults: function (containerId, poiList) {
1978
+ const resultListContainer = document.getElementById(`${containerId}-results`);
1979
+ if (!resultListContainer) return;
1980
+
1981
+ // 清空容器内容
1982
+ resultListContainer.innerHTML = '';
1983
+
1984
+ if (!poiList || poiList.length === 0) {
1985
+ resultListContainer.innerHTML = '<div class="no-results">未找到相关结果</div>';
1986
+ resultListContainer.style.display = 'block';
1987
+ return;
1988
+ }
1989
+
1990
+ // 创建结果列表
1991
+ const resultList = document.createElement('ul');
1992
+ resultList.className = 'search-result-list';
1993
+
1994
+ // 为每个POI创建列表项
1995
+ poiList.forEach((poi, index) => {
1996
+ const listItem = document.createElement('li');
1997
+ listItem.className = 'search-result-item';
1998
+ listItem.dataset.index = index;
1999
+
2000
+ // 设置列表项内容
2001
+ listItem.innerHTML = `
2002
+ <div class="result-item-header">
2003
+ <span class="result-item-name">${poi.name || '未知名称'}</span>
2004
+ ${poi.type ? `<span class="result-item-type">${poi.type}</span>` : ''}
2005
+ </div>
2006
+ ${poi.address ? `<div class="result-item-address">${poi.address}</div>` : ''}
2007
+ ${poi.tel ? `<div class="result-item-tel">电话: ${poi.tel}</div>` : ''}
2008
+ `;
2009
+
2010
+ // 绑定点击事件,实现定位功能
2011
+ listItem.addEventListener('mousedown', (e) => {
2012
+ // 使用mousedown而不是click,避免blur事件先触发
2013
+ e.preventDefault();
2014
+ this.focusOnPOI(poi);
2015
+ });
2016
+
2017
+ resultList.appendChild(listItem);
2018
+ });
2019
+
2020
+ resultListContainer.appendChild(resultList);
2021
+ resultListContainer.style.display = 'block';
2022
+ },
2023
+
2024
+ clearSearchResults: function (containerId) {
2025
+ const resultListContainer = document.getElementById(`${containerId}-results`);
2026
+ if (resultListContainer) {
2027
+ resultListContainer.innerHTML = '';
2028
+ resultListContainer.style.display = 'none';
2029
+ }
2030
+
2031
+ // 同时清除地图上的POI结果
2032
+ this.clearPOIResults();
2033
+ },
2034
+
2035
+
2036
+ focusOnPOI: function (poi) {
2037
+ if (!map || !poi || !poi.longitude || !poi.latitude) return;
2038
+
2039
+ // 移动地图到POI位置
2040
+ map.flyTo({
2041
+ center: [poi.longitude, poi.latitude],
2042
+ zoom: 18,
2043
+ essential: true // 动画不受 prefers-reduced-motion 影响
2044
+ });
2045
+
2046
+ // 高亮显示该POI(如果地图上已有POI结果图层)
2047
+ if (map.getSource('poi-results')) {
2048
+ // 创建临时标记
2049
+ const popup = new mapboxgl.Popup({
2050
+ closeButton: false,
2051
+ className: 'poi-focus-popup'
2052
+ })
2053
+ .setLngLat([poi.longitude, poi.latitude])
2054
+ .setHTML(`<div class="poi-focus-content">${poi.name}</div>`)
2055
+ .addTo(map);
2056
+
2057
+ // 3秒后自动关闭弹窗
2058
+ setTimeout(() => {
2059
+ if (popup.isOpen()) {
2060
+ popup.remove();
2061
+ }
2062
+ }, 3000);
2063
+ }
2064
+ },
2065
+
2066
+
2067
+ // ==================== 九、点位标记与拖拽 ====================
2068
+
2069
+ getMapboxPoints: function (data) {
2070
+ if (!data) return [];
2071
+ return data.map(item => [item.longitude, item.latitude]);
2072
+ },
2073
+
2074
+
2075
+ hitPoint: function (map, points, disableDrag = true, onDragEnd) {
2076
+ if (!map) return;
2077
+
2078
+ let pointsArray = Array.isArray(points) ? points : [points];
2079
+
2080
+ // 创建点数据源 - 改进数据验证逻辑,允许坐标值为0
2081
+ const features = pointsArray
2082
+ .filter(point =>
2083
+ typeof point.longitude !== 'undefined' &&
2084
+ typeof point.latitude !== 'undefined' &&
2085
+ point.longitude !== null &&
2086
+ point.latitude !== null
2087
+ )
2088
+ .map((point, idx) => ({
2089
+ type: 'Feature',
2090
+ geometry: {
2091
+ type: 'Point',
2092
+ coordinates: [point.longitude, point.latitude]
2093
+ },
2094
+ properties: {
2095
+ id: point.id,
2096
+ patrolPoint: point.patrolPoint
2097
+ }
2098
+ }));
2099
+
2100
+ // 添加数据源和图层
2101
+ if (!map.getSource('hit-points')) {
2102
+ map.addSource('hit-points', {
2103
+ type: 'geojson',
2104
+ data: {
2105
+ type: 'FeatureCollection',
2106
+ features: features
2107
+ }
2108
+ });
2109
+
2110
+ map.addLayer({
2111
+ id: 'hit-points',
2112
+ type: 'circle',
2113
+ source: 'hit-points',
2114
+ minzoom: 5,
2115
+ maxZoom: 19,
2116
+ layout: {
2117
+ 'visibility': 'visible' // 显式设置图层可见性
2118
+ },
2119
+ paint: {
2120
+ 'circle-radius': 6,
2121
+ 'circle-color': '#3a6bdb',
2122
+ 'circle-stroke-width': 2,
2123
+ 'circle-stroke-color': '#ffffff'
2124
+ }
2125
+ });
2126
+
2127
+ // 添加标签
2128
+ map.addLayer({
2129
+ id: 'hit-point-labels',
2130
+ type: 'symbol',
2131
+ source: 'hit-points',
2132
+ minzoom: 5,
2133
+ maxZoom: 19,
2134
+ layout: {
2135
+ "text-font": ["Microsoft YaHei"],
2136
+ 'text-field': ['get', 'patrolPoint'],
2137
+ 'text-offset': [0, 1.5],
2138
+ 'text-anchor': 'top',
2139
+ 'visibility': 'visible' // 显式设置图层可见性
2140
+ },
2141
+ paint: {
2142
+ 'text-color': '#0093ff'
2143
+ }
2144
+ });
2145
+
2146
+ // 确保图层在最上层显示
2147
+ const layers = map.getStyle().layers;
2148
+ const lastLayerId = layers.length > 0 ? layers[layers.length - 1].id : undefined;
2149
+ if (lastLayerId) {
2150
+ map.moveLayer('hit-points', lastLayerId);
2151
+ map.moveLayer('hit-point-labels', lastLayerId);
2152
+ }
2153
+
2154
+ // 如果不禁用拖拽,则添加拖拽功能
2155
+ if (!disableDrag) {
2156
+ this._enablePointDragging(map, onDragEnd);
2157
+ }
2158
+
2159
+ // 将 disableDrag 状态存储在图层上,便于后续更新时判断
2160
+ map.getLayer('hit-points')._disableDrag = disableDrag;
2161
+ } else {
2162
+ // 更新数据
2163
+ map.getSource('hit-points').setData({
2164
+ type: 'FeatureCollection',
2165
+ features: features
2166
+ });
2167
+
2168
+ // 确保图层可见
2169
+ map.setLayoutProperty('hit-points', 'visibility', 'visible');
2170
+ map.setLayoutProperty('hit-point-labels', 'visibility', 'visible');
2171
+
2172
+ // 检查是否需要更新拖拽功能状态
2173
+ const hitPointsLayer = map.getLayer('hit-points');
2174
+ if (hitPointsLayer && hitPointsLayer._disableDrag !== disableDrag) {
2175
+ if (!disableDrag) {
2176
+ // 启用拖拽功能
2177
+ this._enablePointDragging(map, onDragEnd);
2178
+ } else {
2179
+ // 禁用拖拽功能,移除相关事件监听器
2180
+ map.off('mousedown', 'hit-points');
2181
+ map.off('mouseenter', 'hit-points');
2182
+ map.off('mouseleave', 'hit-points');
2183
+ }
2184
+ // 更新状态
2185
+ hitPointsLayer._disableDrag = disableDrag;
2186
+ }
2187
+ }
2188
+
2189
+ // 调试日志
2190
+ console.log('_hitPoint_ executed with features:', features);
2191
+ console.log('Current zoom level:', map.getZoom());
2192
+ console.log('Layer visibility:',
2193
+ map.getLayoutProperty('hit-points', 'visibility'),
2194
+ map.getLayoutProperty('hit-point-labels', 'visibility')
2195
+ );
2196
+ },
2197
+
2198
+ /**
2199
+ * 启用点位拖拽功能
2200
+ * @param {Object} map - 地图实例
2201
+ * @param {Function} onDragEnd - 拖拽结束回调函数
2202
+ */
2203
+ _enablePointDragging: function (map, onDragEnd) {
2204
+ let isDragging = false;
2205
+ let dragTarget = null;
2206
+ let originalPosition = null;
2207
+ let tooltip = null; // 添加tooltip变量
2208
+
2209
+ // 鼠标按下事件 - 开始拖拽
2210
+ map.on('mousedown', 'hit-points', (e) => {
2211
+ this.enableScrollWheelZoom(false)
2212
+ map.dragPan.disable();
2213
+ isDragging = true;
2214
+ dragTarget = e.features[0];
2215
+ originalPosition = dragTarget.geometry.coordinates.slice();
2216
+
2217
+ // 设置鼠标样式
2218
+ map.getCanvas().style.cursor = 'grabbing';
2219
+
2220
+ // 为dragTarget增加一个tooltip
2221
+ tooltip = new mapboxgl.Popup({
2222
+ closeButton: false,
2223
+ closeOnClick: false,
2224
+ className: 'drag-tooltip'
2225
+ })
2226
+ .setLngLat(dragTarget.geometry.coordinates)
2227
+ .setHTML('<div>拖拽中...</div>')
2228
+ .addTo(map);
2229
+ });
2230
+
2231
+ // 鼠标移动事件 - 执行拖拽
2232
+ map.on('mousemove', (e) => {
2233
+ if (!isDragging || !dragTarget) return;
2234
+
2235
+ // 更新点位位置
2236
+ const updatedFeatures = map.getSource('hit-points')._data.features.map(feature => {
2237
+ if (feature.properties.id === dragTarget.properties.id) {
2238
+ return {
2239
+ ...feature,
2240
+ geometry: {
2241
+ ...feature.geometry,
2242
+ coordinates: [e.lngLat.lng, e.lngLat.lat]
2243
+ }
2244
+ };
2245
+ }
2246
+ return feature;
2247
+ });
2248
+
2249
+ // 更新数据源
2250
+ map.getSource('hit-points').setData({
2251
+ type: 'FeatureCollection',
2252
+ features: updatedFeatures
2253
+ });
2254
+
2255
+ // 更新tooltip位置
2256
+ if (tooltip) {
2257
+ tooltip.setLngLat([e.lngLat.lng, e.lngLat.lat]);
2258
+ }
2259
+ });
2260
+
2261
+ // 鼠标释放事件 - 结束拖拽
2262
+ map.on('mouseup', () => {
2263
+ // 移除tooltip
2264
+ if (tooltip) {
2265
+ tooltip.remove();
2266
+ tooltip = null;
2267
+ }
2268
+ if (isDragging && dragTarget) {
2269
+ isDragging = false;
2270
+
2271
+ // 获取更新后的点位数据
2272
+ const updatedFeatures = map.getSource('hit-points')._data.features;
2273
+ const updatedPoint = updatedFeatures.find(
2274
+ feature => feature.properties.id === dragTarget.properties.id
2275
+ );
2276
+
2277
+ // 调用回调函数返回更新后的点位信息
2278
+ if (onDragEnd && updatedPoint) {
2279
+ onDragEnd({
2280
+ id: updatedPoint.properties.id,
2281
+ patrolPoint: updatedPoint.properties.patrolPoint,
2282
+ longitude: updatedPoint.geometry.coordinates[0],
2283
+ latitude: updatedPoint.geometry.coordinates[1],
2284
+ originalLongitude: originalPosition[0],
2285
+ originalLatitude: originalPosition[1]
2286
+ });
2287
+ }
2288
+
2289
+ dragTarget = null;
2290
+ originalPosition = null;
2291
+
2292
+ this.enableScrollWheelZoom()
2293
+ map.dragPan.enable();
2294
+ }
2295
+
2296
+ // 恢复鼠标样式
2297
+ map.getCanvas().style.cursor = '';
2298
+ });
2299
+
2300
+ // 鼠标离开地图时也结束拖拽
2301
+ map.on('mouseleave', () => {
2302
+ if (isDragging) {
2303
+ isDragging = false;
2304
+ dragTarget = null;
2305
+ originalPosition = null;
2306
+
2307
+ // 移除tooltip
2308
+ if (tooltip) {
2309
+ tooltip.remove();
2310
+ tooltip = null;
2311
+ }
2312
+
2313
+ map.getCanvas().style.cursor = '';
2314
+ }
2315
+ });
2316
+
2317
+ // 设置鼠标悬停样式
2318
+ map.on('mouseenter', 'hit-points', () => {
2319
+ map.getCanvas().style.cursor = 'grab';
2320
+ });
2321
+
2322
+ map.on('mouseleave', 'hit-points', () => {
2323
+ if (!isDragging) {
2324
+ map.getCanvas().style.cursor = '';
2325
+ }
2326
+ });
2327
+ },
2328
+
2329
+ // ==================== 十、绘制工具(polyline) - 线 ====================
2330
+
2331
+ renderLine: function (map, points, options) {
2332
+ if (!map || !points || points.length < 2) return null;
2333
+
2334
+ const coordinates = points.map(p => [p.lng, p.lat]);
2335
+ const sourceId = options && options.id ? 'custom-line-' + options.id : 'custom-line';
2336
+ const layerId = sourceId;
2337
+
2338
+ const config = {
2339
+ enableEditing: false,
2340
+ enableClicking: true,
2341
+ strokeWeight: 5,
2342
+ strokeOpacity: 0.65,
2343
+ color: '#3a6bdb',
2344
+ ...options
2345
+ };
2346
+
2347
+ // 创建线数据源(统一使用 FeatureCollection 格式)
2348
+ if (!map.getSource(sourceId)) {
2349
+ map.addSource(sourceId, {
2350
+ type: 'geojson',
2351
+ data: {
2352
+ type: 'FeatureCollection',
2353
+ features: [{
2354
+ type: 'Feature',
2355
+ geometry: {
2356
+ type: 'LineString',
2357
+ coordinates: coordinates
2358
+ },
2359
+ properties: {
2360
+ id: options.id || Date.now()
2361
+ }
2362
+ }]
2363
+ }
2364
+ });
2365
+
2366
+ map.addLayer({
2367
+ id: layerId,
2368
+ type: 'line',
2369
+ source: sourceId,
2370
+ paint: {
2371
+ 'line-color': config.color,
2372
+ 'line-width': config.strokeWeight,
2373
+ 'line-opacity': config.strokeOpacity
2374
+ }
2375
+ });
2376
+ } else {
2377
+ // 更新数据(统一通过 features[0] 访问,兼容旧格式)
2378
+ const existingData = map.getSource(sourceId)._data;
2379
+ const isFeatureCollection = existingData.hasOwnProperty('features');
2380
+ const geomData = isFeatureCollection ? existingData.features[0] : existingData;
2381
+ geomData.geometry.coordinates = coordinates;
2382
+ geomData.properties = {
2383
+ ...geomData.properties,
2384
+ ...options.properties
2385
+ };
2386
+ map.getSource(sourceId).setData(isFeatureCollection ? existingData : geomData);
2387
+ }
2388
+
2389
+ // 获取更新后的feature(统一从 FeatureCollection 获取)
2390
+ const sourceData = map.getSource(sourceId)._data;
2391
+ const updatedFeature = sourceData.hasOwnProperty('features') ? sourceData.features[0] : sourceData;
2392
+
2393
+ // 先关闭旧的编辑功能,再按需开启
2394
+ this._disableLineEditing(map, sourceId);
2395
+ if (config.enableEditing) {
2396
+ this._enableLineEditing(map, sourceId, config);
2397
+ }
2398
+
2399
+ // 将 sourceId 附加到返回的 feature 上,便于外部操作
2400
+ if (updatedFeature && updatedFeature.properties) {
2401
+ updatedFeature.properties._sourceId = sourceId;
2402
+ }
2403
+
2404
+ return updatedFeature;
2405
+ },
2406
+
2407
+ /**
2408
+ * 启用线段编辑功能
2409
+ * @param {Object} map - 地图实例
2410
+ * @param {string} sourceId - 线段数据源ID
2411
+ * @param {Object} config - 编辑配置
2412
+ */
2413
+ _enableLineEditing: function (map, sourceId, config) {
2414
+ let editingVertexIndex = -1;
2415
+ let isVertexDragging = false;
2416
+
2417
+ const verticesSourceId = sourceId + '-vertices';
2418
+ const verticesLayerId = verticesSourceId;
2419
+
2420
+ // 创建顶点图层以便编辑
2421
+ if (!map.getSource(verticesSourceId)) {
2422
+ map.addSource(verticesSourceId, {
2423
+ type: 'geojson',
2424
+ data: {
2425
+ type: 'FeatureCollection',
2426
+ features: []
2427
+ }
2428
+ });
2429
+
2430
+ map.addLayer({
2431
+ id: verticesLayerId,
2432
+ type: 'circle',
2433
+ source: verticesSourceId,
2434
+ filter: ['==', '$type', 'Point'],
2435
+ paint: {
2436
+ 'circle-radius': 6,
2437
+ 'circle-color': '#ff0000',
2438
+ 'circle-stroke-width': 2,
2439
+ 'circle-stroke-color': '#ffffff'
2440
+ }
2441
+ });
2442
+ }
2443
+
2444
+ // 更新顶点显示(统一使用 FeatureCollection 格式读取坐标)
2445
+ const updateVertices = () => {
2446
+ const lineData = map.getSource(sourceId)._data;
2447
+ const isFeatureCollection = lineData.hasOwnProperty('features');
2448
+ const coordinates = isFeatureCollection
2449
+ ? lineData.features[0].geometry.coordinates
2450
+ : lineData.geometry.coordinates;
2451
+
2452
+ const vertices = coordinates.map((coord, index) => ({
2453
+ type: 'Feature',
2454
+ geometry: {
2455
+ type: 'Point',
2456
+ coordinates: coord
2457
+ },
2458
+ properties: {
2459
+ vertexIndex: index
2460
+ }
2461
+ }));
2462
+
2463
+ map.getSource(verticesSourceId).setData({
2464
+ type: 'FeatureCollection',
2465
+ features: vertices
2466
+ });
2467
+ };
2468
+
2469
+ // 定义事件处理函数(具名引用,便于后续清理)
2470
+ const onVertexMouseDown = (e) => {
2471
+ if (!config.enableEditing) return;
2472
+
2473
+ this.enableScrollWheelZoom(false);
2474
+ map.dragPan.disable();
2475
+ editingVertexIndex = e.features[0].properties.vertexIndex;
2476
+ isVertexDragging = true;
2477
+
2478
+ // 设置鼠标样式
2479
+ map.getCanvas().style.cursor = 'grabbing';
2480
+ };
2481
+
2482
+ const onVertexMouseMove = (e) => {
2483
+ if (!isVertexDragging || editingVertexIndex === -1 || !config.enableEditing) return;
2484
+
2485
+ // 更新线段坐标(兼容 Feature 和 FeatureCollection 两种格式)
2486
+ const source = map.getSource(sourceId);
2487
+ const data = source._data;
2488
+ const isFeatureCollection = data.hasOwnProperty('features');
2489
+ const coordinates = isFeatureCollection
2490
+ ? data.features[0].geometry.coordinates
2491
+ : data.geometry.coordinates;
2492
+
2493
+ // 更新对应顶点的坐标
2494
+ coordinates[editingVertexIndex] = [e.lngLat.lng, e.lngLat.lat];
2495
+
2496
+ source.setData(data);
2497
+
2498
+ // 更新顶点显示
2499
+ updateVertices();
2500
+ };
2501
+
2502
+ const onVertexMouseUp = () => {
2503
+ if (isVertexDragging) {
2504
+ isVertexDragging = false;
2505
+ editingVertexIndex = -1;
2506
+
2507
+ // 触发编辑完成回调
2508
+ if (config.onEditComplete) {
2509
+ const sourceData = map.getSource(sourceId)._data;
2510
+ const updatedFeature = sourceData.hasOwnProperty('features')
2511
+ ? sourceData.features[0]
2512
+ : sourceData;
2513
+ config.onEditComplete(updatedFeature);
2514
+ }
2515
+
2516
+ this.enableScrollWheelZoom();
2517
+ map.dragPan.enable();
2518
+ }
2519
+
2520
+ // 恢复鼠标样式
2521
+ map.getCanvas().style.cursor = '';
2522
+ };
2523
+
2524
+ const onVertexMouseEnter = () => {
2525
+ if (config.enableEditing) {
2526
+ map.getCanvas().style.cursor = 'crosshair';
2527
+ }
2528
+ };
2529
+
2530
+ const onVertexMouseLeave = () => {
2531
+ if (!isVertexDragging && config.enableEditing) {
2532
+ map.getCanvas().style.cursor = '';
2533
+ }
2534
+ };
2535
+
2536
+ // 绑定事件
2537
+ map.on('mousedown', verticesLayerId, onVertexMouseDown);
2538
+ map.on('mousemove', onVertexMouseMove);
2539
+ map.on('mouseup', onVertexMouseUp);
2540
+ map.on('mouseenter', verticesLayerId, onVertexMouseEnter);
2541
+ map.on('mouseleave', verticesLayerId, onVertexMouseLeave);
2542
+
2543
+ // 保存清理引用到 source 的 _editHandlers 上
2544
+ const source = map.getSource(sourceId);
2545
+ if (source) {
2546
+ source._editHandlers = {
2547
+ verticesSourceId: verticesSourceId,
2548
+ verticesLayerId: verticesLayerId,
2549
+ sourceId: sourceId,
2550
+ onVertexMouseDown: onVertexMouseDown,
2551
+ onVertexMouseMove: onVertexMouseMove,
2552
+ onVertexMouseUp: onVertexMouseUp,
2553
+ onVertexMouseEnter: onVertexMouseEnter,
2554
+ onVertexMouseLeave: onVertexMouseLeave
2555
+ };
2556
+ }
2557
+
2558
+ // 初始显示顶点
2559
+ if (config.enableEditing) {
2560
+ updateVertices();
2561
+ }
2562
+ },
2563
+
2564
+ /**
2565
+ * 禁用线段编辑功能,清理事件和顶点图层
2566
+ * @param {Object} map - 地图实例
2567
+ * @param {string} sourceId - 线段数据源ID
2568
+ */
2569
+ _disableLineEditing: function (map, sourceId) {
2570
+ if (!map) return;
2571
+ const srcId = sourceId || 'custom-line';
2572
+ const source = map.getSource(srcId);
2573
+ if (!source || !source._editHandlers) return;
2574
+
2575
+ const handlers = source._editHandlers;
2576
+ const verticesLayerId = handlers.verticesLayerId;
2577
+ const verticesSourceId = handlers.verticesSourceId;
2578
+
2579
+ // 移除事件监听
2580
+ if (handlers.onVertexMouseDown) {
2581
+ map.off('mousedown', verticesLayerId, handlers.onVertexMouseDown);
2582
+ }
2583
+ if (handlers.onVertexMouseMove) {
2584
+ map.off('mousemove', handlers.onVertexMouseMove);
2585
+ }
2586
+ if (handlers.onVertexMouseUp) {
2587
+ map.off('mouseup', handlers.onVertexMouseUp);
2588
+ }
2589
+ if (handlers.onVertexMouseEnter) {
2590
+ map.off('mouseenter', verticesLayerId, handlers.onVertexMouseEnter);
2591
+ }
2592
+ if (handlers.onVertexMouseLeave) {
2593
+ map.off('mouseleave', verticesLayerId, handlers.onVertexMouseLeave);
2594
+ }
2595
+
2596
+ // 移除顶点图层和源
2597
+ if (map.getLayer(verticesLayerId)) {
2598
+ map.removeLayer(verticesLayerId);
2599
+ }
2600
+ if (map.getSource(verticesSourceId)) {
2601
+ map.removeSource(verticesSourceId);
2602
+ }
2603
+
2604
+ // 清除引用
2605
+ delete source._editHandlers;
2606
+
2607
+ // 恢复地图交互
2608
+ this.enableScrollWheelZoom(true);
2609
+ if (map.dragPan && !map.dragPan.isEnabled()) {
2610
+ map.dragPan.enable();
2611
+ }
2612
+ },
2613
+
2614
+ /**
2615
+ * 清理线图层(source + layer + 编辑状态)
2616
+ * @param {Object} map - 地图实例
2617
+ * @param {string} sourceId - 线段数据源ID(可选,默认 'custom-line')
2618
+ */
2619
+ removeLine: function (map, sourceId) {
2620
+ if (!map) return;
2621
+ const srcId = sourceId || 'custom-line';
2622
+
2623
+ // 先关闭编辑
2624
+ this._disableLineEditing(map, srcId);
2625
+
2626
+ // 移除图层再移除数据源
2627
+ if (map.getLayer(srcId)) {
2628
+ map.removeLayer(srcId);
2629
+ }
2630
+ if (map.getSource(srcId)) {
2631
+ map.removeSource(srcId);
2632
+ }
2633
+ },
2634
+
2635
+ // ==================== 十一、绘制工具(point) - 点 ====================
2636
+
2637
+ /**
2638
+ * 绘制点
2639
+ * @param map 地图实例
2640
+ * @param point 点对象
2641
+ * @param options 绘制配置项
2642
+ * @returns {*|null} 绘制的点对象
2643
+ */
2644
+ renderPoint: function (map, point, options) {
2645
+ if (!map || !point || typeof point.lng === 'undefined' || typeof point.lat === 'undefined') return null;
2646
+
2647
+ const coordinates = [point.lng, point.lat];
2648
+ const sourceId = options && options.id ? 'custom-point-' + options.id : 'custom-point';
2649
+ const layerId = sourceId;
2650
+
2651
+ const config = {
2652
+ enableEditing: false,
2653
+ enableClicking: true,
2654
+ radius: 6,
2655
+ color: '#3a6bdb',
2656
+ strokeColor: '#ffffff',
2657
+ strokeWidth: 2,
2658
+ ...options
2659
+ };
2660
+
2661
+ // 创建点数据源(统一使用 FeatureCollection 格式)
2662
+ if (!map.getSource(sourceId)) {
2663
+ map.addSource(sourceId, {
2664
+ type: 'geojson',
2665
+ data: {
2666
+ type: 'FeatureCollection',
2667
+ features: [{
2668
+ type: 'Feature',
2669
+ geometry: {
2670
+ type: 'Point',
2671
+ coordinates: coordinates
2672
+ },
2673
+ properties: {
2674
+ id: point.id || Date.now()
2675
+ }
2676
+ }]
2677
+ }
2678
+ });
2679
+
2680
+ map.addLayer({
2681
+ id: layerId,
2682
+ type: 'circle',
2683
+ source: sourceId,
2684
+ paint: {
2685
+ 'circle-radius': config.radius,
2686
+ 'circle-color': config.color,
2687
+ 'circle-stroke-width': config.strokeWidth,
2688
+ 'circle-stroke-color': config.strokeColor
2689
+ }
2690
+ });
2691
+ } else {
2692
+ // 更新数据(兼容 Feature 和 FeatureCollection 两种格式)
2693
+ const existingData = map.getSource(sourceId)._data;
2694
+ const isFeatureCollection = existingData.hasOwnProperty('features');
2695
+ const geomData = isFeatureCollection ? existingData.features[0] : existingData;
2696
+ geomData.geometry.coordinates = coordinates;
2697
+ geomData.properties = {
2698
+ ...geomData.properties,
2699
+ ...point.properties
2700
+ };
2701
+
2702
+ map.getSource(sourceId).setData(isFeatureCollection ? existingData : geomData);
2703
+ }
2704
+
2705
+ // 获取更新后的feature(统一从 FeatureCollection 获取)
2706
+ const sourceData = map.getSource(sourceId)._data;
2707
+ const updatedFeature = sourceData.hasOwnProperty('features') ? sourceData.features[0] : sourceData;
2708
+
2709
+ // 先关闭旧的编辑功能,再按需开启
2710
+ this._disablePointEditing(map, sourceId);
2711
+ if (config.enableEditing) {
2712
+ this._enablePointEditing(map, sourceId, config);
2713
+ }
2714
+
2715
+ // 附加 sourceId 便于外部操作
2716
+ if (updatedFeature && updatedFeature.properties) {
2717
+ updatedFeature.properties._sourceId = sourceId;
2718
+ }
2719
+
2720
+ return updatedFeature;
2721
+ },
2722
+
2723
+ /**
2724
+ * 启用点编辑功能
2725
+ * @param {Object} map - 地图实例
2726
+ * @param {string} sourceId - 点数据源ID
2727
+ * @param {Object} config - 编辑配置
2728
+ */
2729
+ _enablePointEditing: function (map, sourceId, config) {
2730
+ let isDragging = false;
2731
+ let dragStartPos = null;
2732
+
2733
+ // 定义事件处理函数(具名引用,便于后续清理)
2734
+ const onPointMouseDown = (e) => {
2735
+ if (!config.enableEditing) return;
2736
+
2737
+ this.enableScrollWheelZoom(false);
2738
+ map.dragPan.disable();
2739
+ isDragging = true;
2740
+ dragStartPos = e.lngLat;
2741
+
2742
+ // 设置鼠标样式
2743
+ map.getCanvas().style.cursor = 'grabbing';
2744
+ };
2745
+
2746
+ const onPointMouseMove = (e) => {
2747
+ if (!isDragging || !config.enableEditing) return;
2748
+
2749
+ // 更新坐标(兼容 Feature 和 FeatureCollection 两种格式)
2750
+ const source = map.getSource(sourceId);
2751
+ const data = source._data;
2752
+ const isFeatureCollection = data.hasOwnProperty('features');
2753
+ const geomData = isFeatureCollection ? data.features[0] : data;
2754
+ geomData.geometry.coordinates = [e.lngLat.lng, e.lngLat.lat];
2755
+ source.setData(data);
2756
+ };
2757
+
2758
+ const onPointMouseUp = () => {
2759
+ if (isDragging) {
2760
+ isDragging = false;
2761
+
2762
+ // 触发编辑完成回调
2763
+ if (config.onEditComplete) {
2764
+ const sourceData = map.getSource(sourceId)._data;
2765
+ const updatedFeature = sourceData.hasOwnProperty('features') ? sourceData.features[0] : sourceData;
2766
+ config.onEditComplete(updatedFeature);
2767
+ }
2768
+
2769
+ this.enableScrollWheelZoom();
2770
+ map.dragPan.enable();
2771
+ }
2772
+
2773
+ // 恢复鼠标样式
2774
+ map.getCanvas().style.cursor = '';
2775
+ };
2776
+
2777
+ const onPointMouseEnter = () => {
2778
+ if (config.enableEditing) {
2779
+ map.getCanvas().style.cursor = 'grab';
2780
+ }
2781
+ };
2782
+
2783
+ const onPointMouseLeave = () => {
2784
+ if (!isDragging && config.enableEditing) {
2785
+ map.getCanvas().style.cursor = '';
2786
+ }
2787
+ };
2788
+
2789
+ // 绑定事件
2790
+ map.on('mousedown', sourceId, onPointMouseDown);
2791
+ map.on('mousemove', onPointMouseMove);
2792
+ map.on('mouseup', onPointMouseUp);
2793
+ map.on('mouseenter', sourceId, onPointMouseEnter);
2794
+ map.on('mouseleave', sourceId, onPointMouseLeave);
2795
+
2796
+ // 保存清理引用到 source 上
2797
+ const source = map.getSource(sourceId);
2798
+ if (source) {
2799
+ source._editHandlers = {
2800
+ sourceId: sourceId,
2801
+ onPointMouseDown: onPointMouseDown,
2802
+ onPointMouseMove: onPointMouseMove,
2803
+ onPointMouseUp: onPointMouseUp,
2804
+ onPointMouseEnter: onPointMouseEnter,
2805
+ onPointMouseLeave: onPointMouseLeave
2806
+ };
2807
+ }
2808
+ },
2809
+
2810
+ /**
2811
+ * 禁用点编辑功能,清理事件
2812
+ * @param {Object} map - 地图实例
2813
+ * @param {string} sourceId - 点数据源ID
2814
+ */
2815
+ _disablePointEditing: function (map, sourceId) {
2816
+ if (!map) return;
2817
+ const srcId = sourceId || 'custom-point';
2818
+ const source = map.getSource(srcId);
2819
+ if (!source || !source._editHandlers) return;
2820
+
2821
+ const handlers = source._editHandlers;
2822
+
2823
+ if (handlers.onPointMouseDown) {
2824
+ map.off('mousedown', srcId, handlers.onPointMouseDown);
2825
+ }
2826
+ if (handlers.onPointMouseMove) {
2827
+ map.off('mousemove', handlers.onPointMouseMove);
2828
+ }
2829
+ if (handlers.onPointMouseUp) {
2830
+ map.off('mouseup', handlers.onPointMouseUp);
2831
+ }
2832
+ if (handlers.onPointMouseEnter) {
2833
+ map.off('mouseenter', srcId, handlers.onPointMouseEnter);
2834
+ }
2835
+ if (handlers.onPointMouseLeave) {
2836
+ map.off('mouseleave', srcId, handlers.onPointMouseLeave);
2837
+ }
2838
+
2839
+ delete source._editHandlers;
2840
+
2841
+ // 恢复地图交互
2842
+ this.enableScrollWheelZoom(true);
2843
+ if (map.dragPan && !map.dragPan.isEnabled()) {
2844
+ map.dragPan.enable();
2845
+ }
2846
+ },
2847
+
2848
+ /**
2849
+ * 清理点图层
2850
+ * @param {Object} map - 地图实例
2851
+ * @param {string} sourceId - 点数据源ID(可选,默认 'custom-point')
2852
+ */
2853
+ removePoint: function (map, sourceId) {
2854
+ if (!map) return;
2855
+ const srcId = sourceId || 'custom-point';
2856
+
2857
+ this._disablePointEditing(map, srcId);
2858
+
2859
+ if (map.getLayer(srcId)) {
2860
+ map.removeLayer(srcId);
2861
+ }
2862
+ if (map.getSource(srcId)) {
2863
+ map.removeSource(srcId);
2864
+ }
2865
+ },
2866
+
2867
+
2868
+ // ==================== 十二、绘制工具(polygon) - 面 ====================
2869
+
2870
+ renderPolygon: function (map, points, options) {
2871
+ if (!map || !points || points.length < 3) return null;
2872
+
2873
+ // 确保多边形闭合
2874
+ const coordinates = [...points.map(p => [p.lng, p.lat])];
2875
+ if (coordinates[0][0] !== coordinates[coordinates.length - 1][0] ||
2876
+ coordinates[0][1] !== coordinates[coordinates.length - 1][1]) {
2877
+ coordinates.push(coordinates[0]); // 闭合多边形
2878
+ }
2879
+
2880
+ const sourceId = options && options.id ? 'custom-polygon-' + options.id : 'custom-polygon';
2881
+ const fillLayerId = sourceId + '-fill';
2882
+ const strokeLayerId = sourceId + '-stroke';
2883
+
2884
+ const config = {
2885
+ enableEditing: false,
2886
+ enableClicking: true,
2887
+ fillColor: '#3a6bdb',
2888
+ fillOpacity: 0.4,
2889
+ strokeColor: '#3a6bdb',
2890
+ strokeWidth: 2,
2891
+ ...options
2892
+ };
2893
+
2894
+ // 创建多边形数据源(统一使用 FeatureCollection 格式)
2895
+ if (!map.getSource(sourceId)) {
2896
+ map.addSource(sourceId, {
2897
+ type: 'geojson',
2898
+ data: {
2899
+ type: 'FeatureCollection',
2900
+ features: [{
2901
+ type: 'Feature',
2902
+ geometry: {
2903
+ type: 'Polygon',
2904
+ coordinates: [coordinates]
2905
+ },
2906
+ properties: {
2907
+ id: options.id || Date.now()
2908
+ }
2909
+ }]
2910
+ }
2911
+ });
2912
+
2913
+ map.addLayer({
2914
+ id: fillLayerId,
2915
+ type: 'fill',
2916
+ source: sourceId,
2917
+ paint: {
2918
+ 'fill-color': config.fillColor,
2919
+ 'fill-opacity': config.fillOpacity
2920
+ }
2921
+ });
2922
+
2923
+ map.addLayer({
2924
+ id: strokeLayerId,
2925
+ type: 'line',
2926
+ source: sourceId,
2927
+ paint: {
2928
+ 'line-color': config.strokeColor,
2929
+ 'line-width': config.strokeWidth
2930
+ }
2931
+ });
2932
+ } else {
2933
+ // 更新数据(兼容旧格式)
2934
+ const existingData = map.getSource(sourceId)._data;
2935
+ const isFeatureCollection = existingData.hasOwnProperty('features');
2936
+ const geomData = isFeatureCollection ? existingData.features[0] : existingData;
2937
+ geomData.geometry.coordinates = [coordinates];
2938
+ geomData.properties = {
2939
+ ...geomData.properties,
2940
+ ...options.properties
2941
+ };
2942
+
2943
+ map.getSource(sourceId).setData(isFeatureCollection ? existingData : geomData);
2944
+ }
2945
+
2946
+ // 获取更新后的feature(统一从 FeatureCollection 获取)
2947
+ const sourceData = map.getSource(sourceId)._data;
2948
+ const updatedFeature = sourceData.hasOwnProperty('features') ? sourceData.features[0] : sourceData;
2949
+
2950
+ // 先关闭旧的编辑功能,再按需开启
2951
+ this._disablePolygonEditing(map, sourceId);
2952
+ if (config.enableEditing) {
2953
+ this._enablePolygonEditing(map, sourceId, config);
2954
+ }
2955
+
2956
+ // 附加 sourceId 便于外部操作
2957
+ if (updatedFeature && updatedFeature.properties) {
2958
+ updatedFeature.properties._sourceId = sourceId;
2959
+ }
2960
+
2961
+ return updatedFeature;
2962
+ },
2963
+
2964
+ /**
2965
+ * 启用多边形编辑功能
2966
+ * @param {Object} map - 地图实例
2967
+ * @param {string} sourceId - 多边形数据源ID
2968
+ * @param {Object} config - 编辑配置
2969
+ */
2970
+ _enablePolygonEditing: function (map, sourceId, config) {
2971
+ let editingVertexIndex = -1;
2972
+ let isVertexDragging = false;
2973
+
2974
+ const verticesSourceId = sourceId + '-vertices';
2975
+ const verticesLayerId = verticesSourceId;
2976
+
2977
+ // 创建顶点图层以便编辑
2978
+ if (!map.getSource(verticesSourceId)) {
2979
+ map.addSource(verticesSourceId, {
2980
+ type: 'geojson',
2981
+ data: {
2982
+ type: 'FeatureCollection',
2983
+ features: []
2984
+ }
2985
+ });
2986
+
2987
+ map.addLayer({
2988
+ id: verticesLayerId,
2989
+ type: 'circle',
2990
+ source: verticesSourceId,
2991
+ filter: ['==', '$type', 'Point'],
2992
+ paint: {
2993
+ 'circle-radius': 6,
2994
+ 'circle-color': '#ff0000',
2995
+ 'circle-stroke-width': 2,
2996
+ 'circle-stroke-color': '#ffffff'
2997
+ }
2998
+ });
2999
+ }
3000
+
3001
+ // 更新顶点显示(兼容新旧格式)
3002
+ const updateVertices = () => {
3003
+ const polygonData = map.getSource(sourceId)._data;
3004
+ const isFeatureCollection = polygonData.hasOwnProperty('features');
3005
+ let coordinates;
3006
+ if (isFeatureCollection) {
3007
+ coordinates = polygonData.features[0].geometry.coordinates[0];
3008
+ } else {
3009
+ coordinates = polygonData.geometry.coordinates[0];
3010
+ }
3011
+
3012
+ const vertices = coordinates.slice(0, -1).map((coord, index) => ({ // 不包含最后一个重复点
3013
+ type: 'Feature',
3014
+ geometry: {
3015
+ type: 'Point',
3016
+ coordinates: coord
3017
+ },
3018
+ properties: {
3019
+ vertexIndex: index
3020
+ }
3021
+ }));
3022
+
3023
+ map.getSource(verticesSourceId).setData({
3024
+ type: 'FeatureCollection',
3025
+ features: vertices
3026
+ });
3027
+ };
3028
+
3029
+ // 定义事件处理函数(具名引用,便于后续清理)
3030
+ const onVertexMouseDown = (e) => {
3031
+ if (!config.enableEditing) return;
3032
+
3033
+ this.enableScrollWheelZoom(false);
3034
+ map.dragPan.disable();
3035
+ editingVertexIndex = e.features[0].properties.vertexIndex;
3036
+ isVertexDragging = true;
3037
+
3038
+ // 设置鼠标样式
3039
+ map.getCanvas().style.cursor = 'grabbing';
3040
+ };
3041
+
3042
+ const onVertexMouseMove = (e) => {
3043
+ if (!isVertexDragging || editingVertexIndex === -1 || !config.enableEditing) return;
3044
+
3045
+ // 更新多边形坐标(兼容 Feature 和 FeatureCollection 两种格式)
3046
+ const source = map.getSource(sourceId);
3047
+ const data = source._data;
3048
+ const isFeatureCollection = data.hasOwnProperty('features');
3049
+ const coordinates = isFeatureCollection
3050
+ ? data.features[0].geometry.coordinates[0]
3051
+ : data.geometry.coordinates[0];
3052
+
3053
+ // 更新对应顶点的坐标
3054
+ coordinates[editingVertexIndex] = [e.lngLat.lng, e.lngLat.lat];
3055
+ // 如果是第一个点,也要更新最后一个点(因为多边形是闭合的)
3056
+ if (editingVertexIndex === 0) {
3057
+ coordinates[coordinates.length - 1] = [e.lngLat.lng, e.lngLat.lat];
3058
+ }
3059
+
3060
+ source.setData(data);
3061
+
3062
+ // 更新顶点显示
3063
+ updateVertices();
3064
+ };
3065
+
3066
+ const onVertexMouseUp = () => {
3067
+ if (isVertexDragging) {
3068
+ isVertexDragging = false;
3069
+ editingVertexIndex = -1;
3070
+
3071
+ // 触发编辑完成回调
3072
+ if (config.onEditComplete) {
3073
+ const sourceData = map.getSource(sourceId)._data;
3074
+ const updatedFeature = sourceData.hasOwnProperty('features')
3075
+ ? sourceData.features[0]
3076
+ : sourceData;
3077
+ config.onEditComplete(updatedFeature);
3078
+ }
3079
+
3080
+ this.enableScrollWheelZoom();
3081
+ map.dragPan.enable();
3082
+ }
3083
+
3084
+ // 恢复鼠标样式
3085
+ map.getCanvas().style.cursor = '';
3086
+ };
3087
+
3088
+ const onVertexMouseEnter = () => {
3089
+ if (config.enableEditing) {
3090
+ map.getCanvas().style.cursor = 'crosshair';
3091
+ }
3092
+ };
3093
+
3094
+ const onVertexMouseLeave = () => {
3095
+ if (!isVertexDragging && config.enableEditing) {
3096
+ map.getCanvas().style.cursor = '';
3097
+ }
3098
+ };
3099
+
3100
+ // 绑定事件
3101
+ map.on('mousedown', verticesLayerId, onVertexMouseDown);
3102
+ map.on('mousemove', onVertexMouseMove);
3103
+ map.on('mouseup', onVertexMouseUp);
3104
+ map.on('mouseenter', verticesLayerId, onVertexMouseEnter);
3105
+ map.on('mouseleave', verticesLayerId, onVertexMouseLeave);
3106
+
3107
+ // 保存清理引用
3108
+ const source = map.getSource(sourceId);
3109
+ if (source) {
3110
+ source._editHandlers = {
3111
+ verticesSourceId: verticesSourceId,
3112
+ verticesLayerId: verticesLayerId,
3113
+ sourceId: sourceId,
3114
+ onVertexMouseDown: onVertexMouseDown,
3115
+ onVertexMouseMove: onVertexMouseMove,
3116
+ onVertexMouseUp: onVertexMouseUp,
3117
+ onVertexMouseEnter: onVertexMouseEnter,
3118
+ onVertexMouseLeave: onVertexMouseLeave
3119
+ };
3120
+ }
3121
+
3122
+ // 初始显示顶点
3123
+ if (config.enableEditing) {
3124
+ updateVertices();
3125
+ }
3126
+ },
3127
+
3128
+ /**
3129
+ * 禁用多边形编辑功能,清理事件和顶点图层
3130
+ * @param {Object} map - 地图实例
3131
+ * @param {string} sourceId - 多边形数据源ID
3132
+ */
3133
+ _disablePolygonEditing: function (map, sourceId) {
3134
+ if (!map) return;
3135
+ const srcId = sourceId || 'custom-polygon';
3136
+ const source = map.getSource(srcId);
3137
+ if (!source || !source._editHandlers) return;
3138
+
3139
+ const handlers = source._editHandlers;
3140
+ const verticesLayerId = handlers.verticesLayerId;
3141
+ const verticesSourceId = handlers.verticesSourceId;
3142
+
3143
+ // 移除事件监听
3144
+ if (handlers.onVertexMouseDown) {
3145
+ map.off('mousedown', verticesLayerId, handlers.onVertexMouseDown);
3146
+ }
3147
+ if (handlers.onVertexMouseMove) {
3148
+ map.off('mousemove', handlers.onVertexMouseMove);
3149
+ }
3150
+ if (handlers.onVertexMouseUp) {
3151
+ map.off('mouseup', handlers.onVertexMouseUp);
3152
+ }
3153
+ if (handlers.onVertexMouseEnter) {
3154
+ map.off('mouseenter', verticesLayerId, handlers.onVertexMouseEnter);
3155
+ }
3156
+ if (handlers.onVertexMouseLeave) {
3157
+ map.off('mouseleave', verticesLayerId, handlers.onVertexMouseLeave);
3158
+ }
3159
+
3160
+ // 移除顶点图层和源
3161
+ if (map.getLayer(verticesLayerId)) {
3162
+ map.removeLayer(verticesLayerId);
3163
+ }
3164
+ if (map.getSource(verticesSourceId)) {
3165
+ map.removeSource(verticesSourceId);
3166
+ }
3167
+
3168
+ // 清除引用
3169
+ delete source._editHandlers;
3170
+
3171
+ // 恢复地图交互
3172
+ this.enableScrollWheelZoom(true);
3173
+ if (map.dragPan && !map.dragPan.isEnabled()) {
3174
+ map.dragPan.enable();
3175
+ }
3176
+ },
3177
+
3178
+ /**
3179
+ * 清理多边形图层
3180
+ * @param {Object} map - 地图实例
3181
+ * @param {string} sourceId - 多边形数据源ID(可选,默认 'custom-polygon')
3182
+ */
3183
+ removePolygon: function (map, sourceId) {
3184
+ if (!map) return;
3185
+ const srcId = sourceId || 'custom-polygon';
3186
+
3187
+ this._disablePolygonEditing(map, srcId);
3188
+
3189
+ const fillLayerId = srcId + '-fill';
3190
+ const strokeLayerId = srcId + '-stroke';
3191
+
3192
+ if (map.getLayer(fillLayerId)) {
3193
+ map.removeLayer(fillLayerId);
3194
+ }
3195
+ if (map.getLayer(strokeLayerId)) {
3196
+ map.removeLayer(strokeLayerId);
3197
+ }
3198
+ if (map.getSource(srcId)) {
3199
+ map.removeSource(srcId);
3200
+ }
3201
+ },
3202
+
3203
+ // ==================== 十三、网格与辅助工具 ====================
3204
+
3205
+ _drawGridWithCenterLabels: function (map, options = {}) {
3206
+ if (!map) return;
3207
+
3208
+ const {
3209
+ interval = 1,
3210
+ color = '#0066cc',
3211
+ width = 1,
3212
+ showLabels = true,
3213
+ showCenterLabels = true
3214
+ } = options;
3215
+
3216
+ const features = [];
3217
+ const labelFeatures = [];
3218
+ const centerLabelFeatures = [];
3219
+
3220
+ // 中国范围经纬度网格
3221
+ // 73.55, 3.85, 135.08, 53.55
3222
+ const minLng = mapConfig.mapExtent[0], maxLng = mapConfig.mapExtent[2];
3223
+ const minLat = mapConfig.mapExtent[1], maxLat = mapConfig.mapExtent[3];
3224
+
3225
+ // 经线
3226
+ for (let lng = Math.ceil(minLng); lng <= Math.floor(maxLng); lng += interval) {
3227
+ const coordinates = [];
3228
+ for (let lat = minLat; lat <= maxLat; lat += 0.1) {
3229
+ coordinates.push([lng, lat]);
3230
+ }
3231
+ features.push({
3232
+ type: 'Feature',
3233
+ geometry: {
3234
+ type: 'LineString',
3235
+ coordinates: coordinates
3236
+ },
3237
+ properties: {
3238
+ type: 'longitude',
3239
+ value: lng
3240
+ }
3241
+ });
3242
+
3243
+ // 添加经度标签
3244
+ if (showLabels) {
3245
+ labelFeatures.push({
3246
+ type: 'Feature',
3247
+ geometry: {
3248
+ type: 'Point',
3249
+ coordinates: [lng, minLat]
3250
+ },
3251
+ properties: {
3252
+ text: `${lng}°`
3253
+ }
3254
+ });
3255
+ }
3256
+ }
3257
+
3258
+ // 纬线
3259
+ for (let lat = Math.ceil(minLat); lat <= Math.floor(maxLat); lat += interval) {
3260
+ const coordinates = [];
3261
+ for (let lng = minLng; lng <= maxLng; lng += 0.1) {
3262
+ coordinates.push([lng, lat]);
3263
+ }
3264
+ features.push({
3265
+ type: 'Feature',
3266
+ geometry: {
3267
+ type: 'LineString',
3268
+ coordinates: coordinates
3269
+ },
3270
+ properties: {
3271
+ type: 'latitude',
3272
+ value: lat
3273
+ }
3274
+ });
3275
+
3276
+ // 添加纬度标签
3277
+ if (showLabels) {
3278
+ labelFeatures.push({
3279
+ type: 'Feature',
3280
+ geometry: {
3281
+ type: 'Point',
3282
+ coordinates: [minLng, lat]
3283
+ },
3284
+ properties: {
3285
+ text: `${lat}°`
3286
+ }
3287
+ });
3288
+ }
3289
+ }
3290
+
3291
+ // 添加网格中心点标签(显示经纬度区间)
3292
+ if (showCenterLabels) {
3293
+ for (let lng = Math.ceil(minLng); lng < Math.floor(maxLng); lng += interval) {
3294
+ for (let lat = Math.ceil(minLat); lat < Math.floor(maxLat); lat += interval) {
3295
+ // 计算网格中心点
3296
+ const centerLng = lng + interval / 2;
3297
+ const centerLat = lat + interval / 2;
3298
+
3299
+ // 创建区间标签文本
3300
+ const label = `${lng}°~${lng + interval}°\n${lat}°~${lat + interval}°`;
3301
+
3302
+ centerLabelFeatures.push({
3303
+ type: 'Feature',
3304
+ geometry: {
3305
+ type: 'Point',
3306
+ coordinates: [centerLng, centerLat]
3307
+ },
3308
+ properties: {
3309
+ text: label
3310
+ }
3311
+ });
3312
+ }
3313
+ }
3314
+ }
3315
+
3316
+ // 添加网格线数据源和图层
3317
+ if (!map.getSource('longitude-latitude-grid')) {
3318
+ map.addSource('longitude-latitude-grid', {
3319
+ type: 'geojson',
3320
+ data: {
3321
+ type: 'FeatureCollection',
3322
+ features: features
3323
+ }
3324
+ });
3325
+
3326
+ map.addLayer({
3327
+ id: 'longitude-latitude-grid',
3328
+ type: 'line',
3329
+ source: 'longitude-latitude-grid',
3330
+ paint: {
3331
+ 'line-color': color,
3332
+ 'line-width': width,
3333
+ 'line-opacity': 0.6,
3334
+ 'line-dasharray': [2, 2]
3335
+ }
3336
+ });
3337
+ } else {
3338
+ map.getSource('longitude-latitude-grid').setData({
3339
+ type: 'FeatureCollection',
3340
+ features: features
3341
+ });
3342
+ }
3343
+
3344
+ // 添加边界标签数据源和图层
3345
+ if (showLabels && labelFeatures.length > 0) {
3346
+ if (!map.getSource('grid-labels')) {
3347
+ map.addSource('grid-labels', {
3348
+ type: 'geojson',
3349
+ data: {
3350
+ type: 'FeatureCollection',
3351
+ features: labelFeatures
3352
+ }
3353
+ });
3354
+
3355
+ map.addLayer({
3356
+ id: 'grid-labels',
3357
+ type: 'symbol',
3358
+ source: 'grid-labels',
3359
+ layout: {
3360
+ 'text-field': ['get', 'text'],
3361
+ 'text-size': 16,
3362
+ 'text-offset': [0, 1]
3363
+ },
3364
+ paint: {
3365
+ 'text-color': '#ff6b35',
3366
+ 'text-halo-color': '#ffffff',
3367
+ 'text-halo-width': 1,
3368
+ }
3369
+ });
3370
+ } else {
3371
+ map.getSource('grid-labels').setData({
3372
+ type: 'FeatureCollection',
3373
+ features: labelFeatures
3374
+ });
3375
+ }
3376
+ }
3377
+
3378
+ // 添加中心点区间标签数据源和图层(仅在层级10及以上显示)
3379
+ if (showCenterLabels && centerLabelFeatures.length > 0) {
3380
+ if (!map.getSource('grid-center-labels')) {
3381
+ map.addSource('grid-center-labels', {
3382
+ type: 'geojson',
3383
+ data: {
3384
+ type: 'FeatureCollection',
3385
+ features: centerLabelFeatures
3386
+ }
3387
+ });
3388
+
3389
+ map.addLayer({
3390
+ id: 'grid-center-labels',
3391
+ type: 'symbol',
3392
+ source: 'grid-center-labels',
3393
+ layout: {
3394
+ 'text-field': ['get', 'text'],
3395
+ 'text-size': 16,
3396
+ 'text-offset': [0, 0],
3397
+ 'text-anchor': 'center',
3398
+ 'text-justify': 'center',
3399
+ },
3400
+ paint: {
3401
+ 'text-color': '#ff6b35',
3402
+ 'text-halo-color': '#ffffff',
3403
+ 'text-halo-width': 1,
3404
+ }
3405
+ });
3406
+ } else {
3407
+ map.getSource('grid-center-labels').setData({
3408
+ type: 'FeatureCollection',
3409
+ features: centerLabelFeatures
3410
+ });
3411
+ }
3412
+ }
3413
+ },
3414
+
3415
+
3416
+ clearGridWithCenterLabels: function (map) {
3417
+ if (!map) return;
3418
+
3419
+ // 清除网格线
3420
+ if (map.getLayer('longitude-latitude-grid')) {
3421
+ map.removeLayer('longitude-latitude-grid');
3422
+ }
3423
+ if (map.getSource('longitude-latitude-grid')) {
3424
+ map.removeSource('longitude-latitude-grid');
3425
+ }
3426
+
3427
+ // 清除边界标签
3428
+ if (map.getLayer('grid-labels')) {
3429
+ map.removeLayer('grid-labels');
3430
+ }
3431
+ if (map.getSource('grid-labels')) {
3432
+ map.removeSource('grid-labels');
3433
+ }
3434
+
3435
+ // 清除中心点标签
3436
+ if (map.getLayer('grid-center-labels')) {
3437
+ map.removeLayer('grid-center-labels');
3438
+ }
3439
+ if (map.getSource('grid-center-labels')) {
3440
+ map.removeSource('grid-center-labels');
3441
+ }
3442
+ },
3443
+
3444
+
3445
+ countMidFromLine: function (start, end) {
3446
+ return {
3447
+ lng: (start.lng + end.lng) / 2,
3448
+ lat: (start.lat + end.lat) / 2
3449
+ };
3450
+ },
3451
+
3452
+ resetCenterAndZoom: function (map) {
3453
+ if (!map) return;
3454
+ map.jumpTo({center: mapConfig.center, zoom: mapConfig.zoom});
3455
+ },
3456
+
3457
+
3458
+ // ==================== 十四、相机与视角控制 ====================
3459
+
3460
+ enableScrollWheelZoom: function (isOpen = true) {
3461
+ // 进行mapboxgl的scroll(wheel)事件的控制
3462
+ if (!map) return;
3463
+
3464
+ if (isOpen) {
3465
+ map.scrollZoom.enable();
3466
+ } else {
3467
+ map.scrollZoom.disable();
3468
+ }
3469
+ },
3470
+
3471
+
3472
+ initialize() {
3473
+ const map = map;
3474
+ if (!map) return;
3475
+
3476
+ if (this._overlook) {
3477
+ map.setCenter(this.target ? this.target.center2d : this.origin.center2d);
3478
+ map.setZoom(this.target ? this.target.zoom2d : this.origin.zoom2d);
3479
+ map.setPitch(0);
3480
+ map.setBearing(0);
3481
+ } else {
3482
+ map.setCenter(this.target ? this.target.center : this.origin.center);
3483
+ map.setZoom(this.target ? this.target.zoom : this.origin.zoom);
3484
+ map.setPitch(this.target ? this.target.pitch : this.origin.pitch);
3485
+ map.setBearing(this.target ? this.target.bearing : this.origin.bearing);
3486
+ }
3487
+ },
3488
+
3489
+
3490
+ flyInitialize() {
3491
+ if (!map) return;
3492
+
3493
+ // fly with default options to null island
3494
+ if (this._overlook) {
3495
+ map.flyTo({
3496
+ center: this.target ? this.target.center2d : this.origin.center2d,
3497
+ zoom: this.target ? this.target.zoom2d : this.origin.zoom2d,
3498
+ pitch: 0,
3499
+ bearing: 0,
3500
+ });
3501
+ } else {
3502
+ map.flyTo({
3503
+ center: this.target ? this.target.center : this.origin.center,
3504
+ zoom: this.target ? this.target.zoom : this.origin.zoom,
3505
+ pitch: this.target ? this.target.pitch : this.origin.pitch,
3506
+ bearing: this.target ? this.target.bearing : this.origin.bearing,
3507
+ });
3508
+ }
3509
+ },
3510
+
3511
+
3512
+ initBearing() {
3513
+ if (!map) return;
3514
+
3515
+ if (this._overlook) {
3516
+ map.setPitch(0);
3517
+ map.setBearing(0);
3518
+ } else {
3519
+ map.setPitch(this.target ? this.target.pitch : this.origin.pitch);
3520
+ map.setBearing(this.target ? this.target.bearing : this.origin.bearing);
3521
+ }
3522
+ },
3523
+
3524
+
3525
+ overlook(is2D = true) {
3526
+ if (!map) return;
3527
+
3528
+ let pitch = 0, bearing = 0;
3529
+ if (is2D) {
3530
+ this._overlook = true;
3531
+
3532
+ if (this.target) {
3533
+ if (map.getZoom() <= this.target.zoom) {
3534
+ map.setCenter(this.target.center2d);
3535
+ map.setZoom(this.target.zoom2d);
3536
+ }
3537
+ } else {
3538
+ if (map.getZoom() <= this.origin.zoom) {
3539
+ map.setCenter(this.origin.center2d);
3540
+ map.setZoom(this.origin.zoom2d);
3541
+ }
3542
+ }
3543
+ } else {
3544
+ this._overlook = false;
3545
+
3546
+ if (this.target) {
3547
+ if (map.getZoom() <= this.target.zoom) {
3548
+ map.setCenter(this.target.center);
3549
+ map.setZoom(this.target.zoom);
3550
+ }
3551
+ pitch = this.target.pitch;
3552
+ bearing = this.target.bearing;
3553
+ } else {
3554
+ if (map.getZoom() <= this.origin.zoom) {
3555
+ map.setCenter(this.origin.center);
3556
+ map.setZoom(this.origin.zoom);
3557
+ }
3558
+ pitch = this.origin.pitch;
3559
+ bearing = this.origin.bearing;
3560
+ }
3561
+ }
3562
+
3563
+ map.setPitch(pitch);
3564
+ map.setBearing(bearing);
3565
+ },
3566
+
3567
+ /**
3568
+ * 飞行至原点
3569
+ */
3570
+ flyToOrigin() {
3571
+ if (!map) return;
3572
+
3573
+ // 飞行至原点
3574
+ if (this.origin) {
3575
+ map.flyTo({
3576
+ ...this.origin,
3577
+ duration: this.flyingDuration,
3578
+ essential: true,
3579
+ easing: (t) => {
3580
+ return t; // 飞行时间进度, (t === 1) 即飞行结束
3581
+ }
3582
+ }, {
3583
+ // eventData 自定义的事件属性
3584
+ moveend: 'FLYTO_END'
3585
+ });
3586
+ }
3587
+ },
3588
+
3589
+ /**
3590
+ * 飞行到目标点
3591
+ */
3592
+ flyToTarget() {
3593
+ if (!map) return;
3594
+
3595
+ // 飞行至目标点
3596
+ const target = this.target ? this.target : this.origin;
3597
+ const duration = this.target ? this.flyingDuration : 0;
3598
+ if (target) {
3599
+ map.flyTo({
3600
+ ...target, // Fly to the selected target
3601
+ duration: duration, // Animate over 4.5 seconds
3602
+ essential: true, // This animation is considered essential with respect to prefers-reduced-motion
3603
+ easing: (t) => {
3604
+ return t; // 飞行时间进度, (t === 1) 即飞行结束
3605
+ }
3606
+ }, {
3607
+ // eventData 自定义的事件属性
3608
+ moveend: 'FLYTO_END'
3609
+ });
3610
+ }
3611
+ },
3612
+
3613
+ /**
3614
+ * 飞行至目标
3615
+ * @param {Object} target -目标对象
3616
+ *
3617
+ * @summary <target参数:{
3618
+ * center: [],
3619
+ * zoom: zoom,
3620
+ * pitch: pitch,
3621
+ * bearing: bearing
3622
+ * }>
3623
+ */
3624
+ flyTo(target) {
3625
+ if (!map) return;
3626
+
3627
+ map.flyTo({
3628
+ ...target, // Fly to the selected target
3629
+ duration: this.flyingDuration, // Animate over 7.5 seconds
3630
+ essential: true, // This animation is considered essential with respect to prefers-reduced-motion
3631
+ easing: (t) => {
3632
+ return t; // 飞行时间进度, (t === 1) 即飞行结束
3633
+ }
3634
+ }, {
3635
+ // eventData 自定义的事件属性
3636
+ moveend: 'FLYTO'
3637
+ });
3638
+ },
3639
+
3640
+ /**
3641
+ * 改变投影模式
3642
+ * @param {String} mode -投影模式(2d, 3d)
3643
+ */
3644
+ changeMode(mode) {
3645
+ if (mode === this._mode) return;
3646
+
3647
+ this._mode = mode;
3648
+
3649
+ if (!map) return;
3650
+
3651
+ switch (this._mode) {
3652
+ case '2d': {
3653
+ map.setProjection('mercator');
3654
+ break;
3655
+ }
3656
+ case '3d': {
3657
+ map.setProjection('globe');
3658
+ break;
3659
+ }
3660
+ default:
3661
+ break;
3662
+ }
3663
+ },
3664
+
3665
+ /**
3666
+ * 地图视角调整
3667
+ * @param {Object} target -地图视角参数
3668
+ */
3669
+ locationArea(target) { // 默认地图视角参数
3670
+ const defaultCenter = mapConfig.center;
3671
+ const defaultZoom = mapConfig.zoom;
3672
+ const defaultBearing = mapConfig.bearing;
3673
+ const defaultPitch = mapConfig.pitch;
3674
+
3675
+ // 解构传入的参数,若没有传入,则使用默认值
3676
+ let {
3677
+ center = defaultCenter,
3678
+ zoom = defaultZoom,
3679
+ bearing = defaultBearing,
3680
+ pitch = defaultPitch
3681
+ } = target;
3682
+
3683
+ // 校验 center 是否为有效的坐标
3684
+ if (!Array.isArray(center) || center.length !== 2) {
3685
+ console.error('无效的center参数,使用默认中心点');
3686
+ center = defaultCenter;
3687
+ }
3688
+
3689
+ // 校验其他参数是否为数字,若不是则使用默认值
3690
+ const validZoom = typeof zoom === 'number' ? zoom : defaultZoom;
3691
+ const validBearing = typeof bearing === 'number' ? bearing : defaultBearing;
3692
+ const validPitch = typeof pitch === 'number' ? pitch : defaultPitch;
3693
+
3694
+ // 调整地图视角
3695
+ if (map) {
3696
+ map.setCenter(center);
3697
+ map.setZoom(validZoom);
3698
+ map.setBearing(validBearing);
3699
+ map.setPitch(validPitch);
3700
+ } else {
3701
+ console.error('地图实例未初始化');
3702
+ }
3703
+ },
3704
+
3705
+ /**
3706
+ * 合成快照用 canvas:Mapbox 主 canvas + AntV L7 等叠加 WebGL canvas。
3707
+ * L7 与 Mapbox 可能像素宽高不一致,不能只匹配「同宽高」;需在导出前 scene.render(),否则会读到空缓冲。
3708
+ *
3709
+ * @returns {HTMLCanvasElement|null}
3710
+ */
3711
+ _compositeSnapshotCanvas() {
3712
+ if (!map) {
3713
+ return null;
3714
+ }
3715
+ if (antv7Scene && typeof antv7Scene.render === "function") {
3716
+ try {
3717
+ antv7Scene.render();
3718
+ } catch (e) {
3719
+ /* ignore */
3720
+ }
3721
+ }
3722
+
3723
+ const mapCanvas = map.getCanvas();
3724
+ const w = mapCanvas.width;
3725
+ const h = mapCanvas.height;
3726
+ const merged = document.createElement("canvas");
3727
+ merged.width = w;
3728
+ merged.height = h;
3729
+ const ctx = merged.getContext("2d");
3730
+ ctx.drawImage(mapCanvas, 0, 0);
3731
+
3732
+ const roots = [];
3733
+ const byId = document.getElementById(this._id);
3734
+ if (byId) {
3735
+ roots.push(byId);
3736
+ }
3737
+ if (typeof map.getContainer === "function") {
3738
+ const mc = map.getContainer();
3739
+ if (mc && roots.indexOf(mc) < 0) {
3740
+ roots.push(mc);
3741
+ }
3742
+ }
3743
+
3744
+ const drawn = new Set([mapCanvas]);
3745
+ const drawOverlay = (c) => {
3746
+ if (!c || drawn.has(c)) {
3747
+ return;
3748
+ }
3749
+ if (!c.width || !c.height) {
3750
+ return;
3751
+ }
3752
+ /* 过滤控件等小 canvas,避免误铺满 */
3753
+ if (c.width < 80 || c.height < 80) {
3754
+ return;
3755
+ }
3756
+ try {
3757
+ if (c.width === w && c.height === h) {
3758
+ ctx.drawImage(c, 0, 0);
3759
+ } else {
3760
+ ctx.drawImage(c, 0, 0, c.width, c.height, 0, 0, w, h);
3761
+ }
3762
+ drawn.add(c);
3763
+ } catch (e) {
3764
+ /* WebGL 未就绪或跨域 */
3765
+ }
3766
+ };
3767
+
3768
+ roots.forEach((root) => {
3769
+ root.querySelectorAll("canvas").forEach((c) => drawOverlay(c));
3770
+ });
3771
+
3772
+ return merged;
3773
+ },
3774
+
3775
+ // ==================== 十五、地图导出 ====================
3776
+
3777
+ exportBlob() {
3778
+ return new Promise((resolve) => {
3779
+ const finish = () => {
3780
+ const merged = this._compositeSnapshotCanvas();
3781
+ if (!merged) {
3782
+ resolve({msg: "error", data: null});
3783
+ return;
3784
+ }
3785
+ merged.toBlob((blob) => {
3786
+ resolve({msg: "success", data: blob});
3787
+ }, "image/png", 0.95);
3788
+ };
3789
+ /* render 后多等一帧再读像素,减少 WebGL 未合成完导致的空白层 */
3790
+ requestAnimationFrame(() => {
3791
+ requestAnimationFrame(finish);
3792
+ });
3793
+ });
3794
+ },
3795
+
3796
+
3797
+ exportBase64() {
3798
+ return new Promise((resolve, reject) => {
3799
+ const finish = () => {
3800
+ const merged = this._compositeSnapshotCanvas();
3801
+ if (!merged) {
3802
+ reject({msg: "error", data: null});
3803
+ return;
3804
+ }
3805
+ merged.toBlob((blob) => {
3806
+ const reader = new FileReader();
3807
+ reader.readAsDataURL(blob);
3808
+ reader.onload = () => {
3809
+ resolve({msg: "success", data: reader.result});
3810
+ };
3811
+ reader.onerror = () => {
3812
+ reject({msg: "error", data: null});
3813
+ };
3814
+ }, "image/png", 0.95);
3815
+ };
3816
+ requestAnimationFrame(() => {
3817
+ requestAnimationFrame(finish);
3818
+ });
3819
+ });
3820
+ },
3821
+ }