mapConfig.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. import {LineLayer, PointLayer, PolygonLayer, Popup, RasterLayer, Scene} from "@antv/l7";
  2. import type {ICameraOptions, ISourceCFG, Point} from "@antv/l7-core";
  3. import {Map as AntvMap} from "@antv/l7-maps";
  4. import {formatStringByTemplate} from "@/utils/string";
  5. import bus from "@/utils/bus";
  6. export let scene: Scene;
  7. // 加载状态
  8. export let loadedStatus = false;
  9. export const imageMap = new Map()
  10. function loadImage(images: any[]) {
  11. images.forEach((item: any) => {
  12. if (!imageMap.has(item.name)) {
  13. imageMap.set(item.name, item.src);
  14. scene.addImage(item.name, item.src);
  15. }
  16. })
  17. }
  18. /**
  19. * 初始化地图
  20. */
  21. export function init(config: any) {
  22. scene = new Scene({
  23. id: 'mapDiv',
  24. map: new AntvMap({
  25. center: [119.6620473872265, 29.415337822470235],
  26. zoom: 7.1,
  27. }),
  28. });
  29. scene.on('loaded', () => {
  30. loadedStatus = true
  31. loadBaseLayer()
  32. // 加载图片
  33. if (config && config.images && config.images.length > 0) {
  34. loadImage(config.images)
  35. }
  36. });
  37. // 地图平移时触发事件
  38. scene.on('mapmove', () => {
  39. console.log('中心点:', scene.getCenter().lng, scene.getCenter().lat, scene.getZoom(), scene.getPitch())
  40. });
  41. }
  42. /**
  43. * 加载底图
  44. */
  45. function loadBaseLayer() {
  46. // 底图服务
  47. const url1 = 'https://t0.tianditu.gov.cn/img_w/wmts?tk=a4eab5a1b0d94268669e192b8799f626&';
  48. const layer1 = new RasterLayer().source(url1, {
  49. parser: {
  50. type: 'rasterTile',
  51. tileSize: 256,
  52. wmtsOptions: {
  53. layer: 'img',
  54. tileMatrixset: 'w',
  55. format: 'tiles',
  56. },
  57. },
  58. });
  59. scene.addLayer(layer1);
  60. // const baseLayer = new RasterLayer().source(
  61. // `https://t1.tianditu.gov.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk=a4eab5a1b0d94268669e192b8799f626}`,
  62. // {
  63. // parser: {
  64. // type: 'rasterTile',
  65. // tileSize: 256,
  66. // }
  67. // }
  68. // );
  69. // scene.addLayer(baseLayer);
  70. }
  71. /**
  72. * 设置地图视角
  73. * @param center 中心点
  74. * @param zoom 层级
  75. * @param pitch 倾斜角度
  76. * @param padding
  77. */
  78. export function setCenter(center: Point, zoom: number, pitch = 0, padding = {}) {
  79. if (center && zoom) {
  80. scene.setZoomAndCenter(zoom, center);
  81. } else if (center) {
  82. scene.setCenter(center, padding as ICameraOptions);
  83. } else if (zoom) {
  84. scene.setZoom(zoom);
  85. }
  86. scene.setPitch(pitch);
  87. }
  88. export function loadMap(option: any) {
  89. if (option.view) {
  90. setCenter(option.view.center, option.view.zoom)
  91. }
  92. if (option.layers) {
  93. // 清空图层
  94. scene.removeAllLayer();
  95. // 加载地图
  96. loadBaseLayer()
  97. option.layers.forEach((layer: any) => {
  98. switch (layer.type) {
  99. case 'point':
  100. createPointByCongfig(layer)
  101. break
  102. // case 'line':
  103. // createLineByCongfig(layer, mapJson)
  104. // break
  105. // case 'polygon':
  106. // createPolygonByCongfig(layer, mapJson)
  107. // break
  108. // case 'mark':
  109. // setMark(config)
  110. // break
  111. }
  112. })
  113. }
  114. }
  115. function createPointByCongfig(config: any) {
  116. console.log('config', config, imageMap)
  117. const layer = new PointLayer({})
  118. .source(config.data, config.dataOptions)
  119. .size(config.size)
  120. .active(config.emphasis.show);
  121. setLayerShape(layer, config.shape);
  122. // 颜色配置
  123. // setLayerColor(layer, config.color);
  124. scene.addLayer(layer);
  125. setMark(config);
  126. // setPopup(layer, config);
  127. // 点击事件
  128. layer.on('click', (e: any) => {
  129. let row = e.feature.properties || e.feature
  130. bus.emit('point_click', {data: row, e})
  131. });
  132. }
  133. function getValueByConditions(data: any, conditions: any, field: any) {
  134. let condition;
  135. for (const item of conditions) {
  136. if (compareByConditions(data, item)) {
  137. condition = item
  138. break
  139. }
  140. }
  141. if (!condition) {
  142. return null;
  143. }
  144. if (field === 'color') {
  145. return condition[field]
  146. }
  147. if (condition[field] !== 'image') {
  148. return condition[field]
  149. }
  150. if (condition[field] === 'image') {
  151. return condition.imageName
  152. }
  153. return null;
  154. }
  155. function compareByConditions(data: any, condition: any) {
  156. switch (condition.cond) {
  157. case 'lt':
  158. if (data < condition.value) {
  159. return true
  160. }
  161. break
  162. case 'lte':
  163. if (data <= condition.value) {
  164. return true
  165. }
  166. break
  167. case 'eq':
  168. if (data == condition.value) {
  169. return true
  170. }
  171. break
  172. case 'gt':
  173. if (data > condition.value) {
  174. return true
  175. }
  176. break
  177. case 'gte':
  178. if (data >= condition.value) {
  179. return true
  180. }
  181. break
  182. case 'ne':
  183. if (data != condition.value) {
  184. return true
  185. }
  186. break
  187. }
  188. return false;
  189. }
  190. /**
  191. * 图层数据配置
  192. * @param dataType
  193. * @returns {{parser: {x: string, y: string, type: string}}|null}
  194. */
  195. function getSourceOptions(dataType: any) {
  196. switch (dataType) {
  197. case 'geojson':
  198. return null;
  199. case 'list':
  200. return {
  201. parser: {
  202. type: 'json',
  203. x: '经度',
  204. y: '纬度',
  205. },
  206. }
  207. default:
  208. }
  209. }
  210. /**
  211. * 图层形状配置
  212. * @param layer
  213. * @param config
  214. */
  215. function setLayerShape(layer: any, config: any) {
  216. if (config.isConstant) {
  217. layer.shape(config.value)
  218. } else {
  219. layer.shape(config.field, config.value)
  220. }
  221. }
  222. /**
  223. * 图层颜色配置
  224. * @param layer
  225. * @param config
  226. */
  227. function setLayerColor(layer: any, config: any) {
  228. if (config.isConstant) {
  229. layer.color(config.value)
  230. } else {
  231. const field = config.field
  232. const conditions = config.conditions
  233. layer.color(field, (field: any) => {
  234. return getValueByConditions(field, conditions, 'color');
  235. });
  236. }
  237. }
  238. export function setMark(config: any) {
  239. if (!config.label.show) {
  240. return
  241. }
  242. // 标注
  243. const markLayer = new PointLayer({})
  244. .source(config.data, config.dataOptions)
  245. .shape(config.label.field, 'text')
  246. .size(16)
  247. .color('#fff')
  248. .style({
  249. textAnchor: config.label.position || 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
  250. textOffset: [0, 40], // 文本相对锚点的偏移量 [水平, 垂直]
  251. spacing: 2, // 字符间距
  252. // padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
  253. // stroke: '#ffffff', // 描边颜色
  254. // strokeWidth: 2, // 描边宽度
  255. // strokeOpacity: 1.0,
  256. });
  257. scene.addLayer(markLayer);
  258. }
  259. function setPopup(layer: any, config: any) {
  260. if (!config.enabled) {
  261. return
  262. }
  263. layer.on(config.trigger, (e: any) => {
  264. let properties = e.feature.properties || e.feature
  265. const content = formatStringByTemplate(properties, config.content)
  266. // offsets: [0, 0], closeButton: false,
  267. const popup = new Popup({})
  268. .setLnglat(e.lngLat)
  269. .setHTML(content);
  270. scene.addPopup(popup);
  271. });
  272. }
  273. /**
  274. * 创建线图层
  275. * @param config 配置
  276. * @param dataType 图层数据类型
  277. * @param mapData 图层数据
  278. */
  279. function createLineByCongfig(config: any, dataType: any, mapData: any) {
  280. const sourceOptions = getSourceOptions(dataType) as ISourceCFG
  281. const layer = new LineLayer({})
  282. .source(mapData, sourceOptions)
  283. .size(1)
  284. .style({
  285. lineType: 'dash',
  286. dashArray: [2, 2],
  287. })
  288. .active(config.active);
  289. scene.addLayer(layer);
  290. setMark(config);
  291. setPopup(layer, config.popup);
  292. }
  293. /**
  294. * 创建面图层
  295. * @param config 配置
  296. * @param dataType 图层数据类型
  297. * @param mapData 图层数据
  298. */
  299. function createPolygonByCongfig(config: any, dataType: any, mapData: any) {
  300. const sourceOptions = getSourceOptions(dataType) as ISourceCFG
  301. const layer = new PolygonLayer({})
  302. .source(mapData, sourceOptions)
  303. .shape('fill')
  304. .active(config.active);
  305. // 颜色配置
  306. setLayerColor(layer, config.color);
  307. scene.addLayer(layer);
  308. setMark(config);
  309. setPopup(layer, config.popup);
  310. }
  311. export function getLegendData(config: any) {
  312. const layers = config.layers
  313. const layerLegend = layers.reduce((acc: any, item: any) => {
  314. if (item.legend && item.legend.data) {
  315. return acc.concat(item.legend.data);
  316. } else {
  317. return acc;
  318. }
  319. }, []);
  320. // return layerLegend.map((item: any) => {
  321. // const data = {label: item.text}
  322. // if (item.shape === 'image') {
  323. // data.imgType = 'img'
  324. // data.src = item.imgSrc
  325. // } else {
  326. // data.imgType = 'svg'
  327. // data.src = item.shape
  328. // data.imgStyle = {fill: item.color}
  329. // }
  330. // return data
  331. // })
  332. return null
  333. }