当前位置:   article > 正文

leaflet将不同类型的marker添加到不同图层,并实现图层切换_leaflet marker

leaflet marker

        leaflet在二维gis开发中使用比较广泛,本人最近也在从事gis相关开发。趁着这两天不是很忙,赶紧将这两天的开发过程记录一下,作为以后工作的参考。

leaflet添加marker的一般步骤:

        上图表现了leaflet添加marker的一般步骤。

初始化地图:

        地图用的是超图的leaflet插件@supermap/iclient-leaflet,官方地址: https://github.com/SuperMap/iClient-JavaScript/tree/master/src/leaflet。选用超图的原因是后期画路径的时候可以很方便的调用超图的服务,另一方面是项目大框架基于超图。

        首先在项目中引入插件,如图:

 

         本人为了方便将两个css下载到了本地,下载链接:https://unpkg.com/leaflet@1.3.1/dist/leaflet.csshttps://iclient.supermap.io/dist/leaflet/iclient-leaflet.min.css,这两个下载链接在官方都有,下载完成在html页面中引入即可。插件引入完成后进行地图的初始化,代码如下:

  1. initMap () {
  2. const host = window.isLocal
  3. ? window.server
  4. : 'https://iserver.supermap.io'
  5. const url = host + '/iserver/services/map-china400/rest/maps/China'
  6. this.mapObj = L.map(this.mapId, {
  7. // center: [0, 0],
  8. center: [45.7413805110411, 127.165046475283],
  9. maxZoom: 18,
  10. zoom: 6,
  11. zoomControl: false
  12. })
  13. L.supermap.tiledMapLayer(url).addTo(this.mapObj)
  14. this.rootLayerGroup = L.featureGroup().addTo(this.mapObj) // 添加根图层(方便管理其他图层)
  15. },

         然后再mounted中调用,如下:

  1. mounted () {
  2. this.$nextTick(() => {
  3. this.initMap()
  4. })
  5. },

 创建icon对象

         在项目中,marker的种类不一,每种marker对应一个图标,因此需要的icon也就不一,加上marker点击高亮的icon,就需要为每个类型的mrker准备两个icon对象,一个默认,一个高亮,这里用两个对象defaultIcons和focusIcons分别保存默认图标和高亮图标(两个对象实际是两个map结构,以类型为key,对应的icon为value)。具体需要几种marker以后台数据为准,这里有一个json文件模拟数据:

  1. {
  2. "code": 200,
  3. "data": [
  4. {
  5. "id": 1,
  6. "lat": "",
  7. "lng": "",
  8. "poiName": "桥梁",
  9. "poiType": "bridge",
  10. "children": [
  11. {
  12. "id": 2,
  13. "lat": 44.9255,
  14. "lng": 127.2017,
  15. "poiName": "佳木斯大桥",
  16. "poiType": "bridge"
  17. },
  18. {
  19. "id": 3,
  20. "lat": 45.7933,
  21. "lng": 128.6749,
  22. "poiName": "佳木斯中桥",
  23. "poiType": "bridge"
  24. },
  25. {
  26. "id": 4,
  27. "lat": 44.9194,
  28. "lng": 128.5764,
  29. "poiName": "佳木斯小桥",
  30. "poiType": "bridge"
  31. },
  32. {
  33. "id": 12,
  34. "lat": 46.500976,
  35. "lng": 125.049838,
  36. "poiName": "桥A",
  37. "poiType": "bridge"
  38. },
  39. {
  40. "id": 13,
  41. "lat": 46.11039,
  42. "lng": 125.305188,
  43. "poiName": "桥B",
  44. "poiType": "bridge"
  45. },
  46. {
  47. "id": 14,
  48. "lat": 46.657439,
  49. "lng": 125.026459,
  50. "poiName": "桥C",
  51. "poiType": "bridge"
  52. },
  53. {
  54. "id": 15,
  55. "lat": 47.744832,
  56. "lng": 128.859247,
  57. "poiName": "桥D",
  58. "poiType": "bridge"
  59. },
  60. {
  61. "id": 16,
  62. "lat": 48.668639,
  63. "lng": 130.477707,
  64. "poiName": "桥E",
  65. "poiType": "bridge"
  66. },
  67. {
  68. "id": 17,
  69. "lat": 47.424955,
  70. "lng": 124.107461,
  71. "poiName": "桥F",
  72. "poiType": "bridge"
  73. },
  74. {
  75. "id": 18,
  76. "lat": 47.39034,
  77. "lng": 123.920893,
  78. "poiName": "桥G",
  79. "poiType": "bridge"
  80. }
  81. ]
  82. },
  83. {
  84. "id": 5,
  85. "lat": "",
  86. "lng": "",
  87. "poiName": "涵洞",
  88. "poiType": "culvert",
  89. "children": [
  90. {
  91. "id": 6,
  92. "lat": 45.7404,
  93. "lng": 127.1621,
  94. "poiName": "涵洞1",
  95. "poiType": "culvert"
  96. },
  97. {
  98. "id": 7,
  99. "lat": 45.44,
  100. "lng": 126.41,
  101. "poiName": "涵洞2",
  102. "poiType": "culvert"
  103. },
  104. {
  105. "id": 8,
  106. "lat": 45.73832834,
  107. "lng": 127.1584935,
  108. "poiName": "涵洞3",
  109. "poiType": "culvert"
  110. },
  111. {
  112. "id": 19,
  113. "lat": 44.599933,
  114. "lng": 129.616987,
  115. "poiName": "隧道A",
  116. "poiType": "culvert"
  117. }
  118. ]
  119. },
  120. {
  121. "id": 9,
  122. "lat": "",
  123. "lng": "",
  124. "poiName": "标志",
  125. "poiType": "trafficSafe",
  126. "children": [
  127. {
  128. "id": 10,
  129. "lat": 45.74045209,
  130. "lng": 127.1617092,
  131. "poiName": "指示标志",
  132. "poiType": "trafficSafe"
  133. },
  134. {
  135. "poiName": "交通路牌",
  136. "poiType": "trafficSafe",
  137. "lat": 45.74045209,
  138. "lng": 128.1617843,
  139. "id": 11
  140. }
  141. ]
  142. }
  143. ]
  144. }

         可以看到这里的数据是一个树状结构,总共有3中marker(父节点的个数),为了方便将图片命名为对应的type,如图:

 获取数据后初始化icon,代码如下:

  1. async getData () {
  2. const dataRes = await axios.get('/static/json/elTreeData.json')
  3. if (dataRes) {
  4. const treeData = dataRes.data.data
  5. this.setIcons(treeData)
  6. }
  7. },
  8. /**
  9. * 初始化Icons
  10. */
  11. setIcons (data) {
  12. data.forEach((item) => {
  13. this.defaultIcons[item.poiType] = L.icon({
  14. iconUrl: '/static/images/' + item.poiType + 'DefaultIcon.png',
  15. iconSize: [48, 60],
  16. iconAnchor: [24, 60],
  17. popupAnchor: [0, -30]
  18. })
  19. this.focusIcons[item.poiType] = L.icon({
  20. iconUrl: '/static/images/' + item.poiType + 'FocusIcon.png',
  21. iconSize: [48, 60],
  22. iconAnchor: [24, 60],
  23. popupAnchor: [0, -30]
  24. })
  25. })
  26. },

 创建marker图层以及marker点

         创建marker的时候需要点聚合,点聚合使用的是leaflet的插件leaflet.markercluster,具体使用方法参照官方,官网地址https://github.com/Leaflet/Leaflet.markercluster,创建marker代码如下:

  1. initMarkers (data) {
  2. data.forEach((item) => {
  3. // marker聚合 markerClusterGroup本质是一个图层,类似fetureGroup
  4. const markerLayer = L.markerClusterGroup({
  5. spiderfyOnMaxZoom: false,
  6. showCoverageOnHover: false,
  7. zoomToBoundsOnClick: false
  8. })
  9. item.children.forEach((item1) => {
  10. const marker = L.marker([item1.lat, item1.lng], {
  11. icon: this.defaultIcons[item1.poiType],
  12. markerId: item1.id,
  13. type: item1.poiType
  14. }).on('click', (ev) => {
  15. this.resetMarker()
  16. ev.target.setIcon(this.focusIcons[ev.target.options.type])
  17. this.focusMaker = ev.target
  18. })
  19. markerLayer.addLayer(marker)
  20. })
  21. this.rootLayerGroup.addLayer(markerLayer) // 将markerLayer添加到根图层
  22. })
  23. },
  24. /**
  25. * 将上一次点击marker的重置为默认图标
  26. */
  27. resetMarker () {
  28. if (this.focusMaker) {
  29. const iconType = this.focusMaker.options.type
  30. this.focusMaker.setIcon(this.defaultIcons[iconType])
  31. }
  32. }

 添加图层切换功能

        图层切换是利用了layerGroup的addLayer() 和 clearLayers()方法, 主要代码如下:

  1. /**
  2. * 初始化checkbox值
  3. */
  4. initCheckGroup (data) {
  5. data.forEach((item) => {
  6. this.checkedMarkerLayerKey.push(item.poiType)
  7. this.markerLayerKeys.push({
  8. name: item.poiName,
  9. poiType: item.poiType
  10. })
  11. })
  12. },
  13. /**
  14. * 图层勾选
  15. */
  16. checkGroupChange (val) {
  17. this.rootLayerGroup.clearLayers()
  18. val.forEach((item) => {
  19. this.rootLayerGroup.addLayer(this.layersObj[item])
  20. })
  21. }

 最终实现效果:

 

        本篇文章作为本人实际项目的参考、复制、粘贴来源,因此有些细节并未提及。最后附上地图vue文件的完整代码。

mapVue完整代码 

  1. <template>
  2. <div class="map-2d">
  3. <div class="markerLayer-control">
  4. <el-checkbox-group
  5. v-model="checkedMarkerLayerKey"
  6. @change="checkGroupChange"
  7. >
  8. <el-checkbox
  9. v-for="item in markerLayerKeys"
  10. :key="item.poiType"
  11. :label="item.poiType"
  12. >
  13. {{ item.name }}
  14. </el-checkbox>
  15. </el-checkbox-group>
  16. </div>
  17. <div class="map2d-container" :id="mapId"></div>
  18. </div>
  19. </template>
  20. <script>
  21. import 'leaflet.markercluster/dist/MarkerCluster.css'
  22. import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
  23. import 'leaflet.markercluster'
  24. import axios from 'axios'
  25. export default {
  26. data () {
  27. return {
  28. mapId: 'map2d', // 地图id
  29. mapObj: null, // 地图对象
  30. rootLayerGroup: null, // 根图层
  31. checkedMarkerLayerKey: [], // 图层勾选值-checkbox-group绑定值
  32. markerLayerKeys: [], // 图层类型-给checkbox用
  33. defaultIcons: {}, // 默认图标
  34. focusIcons: {}, // 高亮图标
  35. layersObj: {} // 存放markerLayer图层,便于图层切换
  36. }
  37. },
  38. mounted () {
  39. this.$nextTick(() => {
  40. this.initMap()
  41. })
  42. },
  43. methods: {
  44. initMap () {
  45. const host = window.isLocal
  46. ? window.server
  47. : 'https://iserver.supermap.io'
  48. const url = host + '/iserver/services/map-china400/rest/maps/China'
  49. this.mapObj = L.map(this.mapId, {
  50. // center: [0, 0],
  51. center: [45.7413805110411, 127.165046475283],
  52. maxZoom: 18,
  53. zoom: 6,
  54. zoomControl: false
  55. })
  56. L.supermap.tiledMapLayer(url).addTo(this.mapObj)
  57. this.rootLayerGroup = L.featureGroup().addTo(this.mapObj) // 添加根图层(方便管理其他图层)
  58. this.getData()
  59. },
  60. async getData () {
  61. const dataRes = await axios.get('/static/json/elTreeData.json')
  62. if (dataRes) {
  63. const treeData = dataRes.data.data
  64. this.setIcons(treeData)
  65. this.initMarkers(treeData)
  66. this.initCheckGroup(treeData)
  67. }
  68. },
  69. /**
  70. * 初始化Icons
  71. */
  72. setIcons (data) {
  73. data.forEach((item) => {
  74. this.defaultIcons[item.poiType] = L.icon({
  75. iconUrl: '/static/images/' + item.poiType + 'DefaultIcon.png',
  76. iconSize: [48, 60],
  77. iconAnchor: [24, 60],
  78. popupAnchor: [0, -30]
  79. })
  80. this.focusIcons[item.poiType] = L.icon({
  81. iconUrl: '/static/images/' + item.poiType + 'FocusIcon.png',
  82. iconSize: [48, 60],
  83. iconAnchor: [24, 60],
  84. popupAnchor: [0, -30]
  85. })
  86. })
  87. },
  88. initMarkers (data) {
  89. data.forEach((item) => {
  90. // marker聚合 markerClusterGroup本质是一个图层,类似fetureGroup
  91. const markerLayer = L.markerClusterGroup({
  92. spiderfyOnMaxZoom: false,
  93. showCoverageOnHover: false,
  94. zoomToBoundsOnClick: false
  95. })
  96. item.children.forEach((item1) => {
  97. const marker = L.marker([item1.lat, item1.lng], {
  98. icon: this.defaultIcons[item1.poiType],
  99. markerId: item1.id,
  100. type: item1.poiType
  101. }).on('click', (ev) => {
  102. this.resetMarker()
  103. ev.target.setIcon(this.focusIcons[ev.target.options.type])
  104. this.focusMaker = ev.target
  105. })
  106. markerLayer.addLayer(marker)
  107. })
  108. this.layersObj[item.poiType] = markerLayer
  109. this.rootLayerGroup.addLayer(markerLayer) // 将markerLayer添加到根图层
  110. })
  111. },
  112. /**
  113. * 将上一次点击marker的重置为默认图标
  114. */
  115. resetMarker () {
  116. if (this.focusMaker) {
  117. const iconType = this.focusMaker.options.type
  118. this.focusMaker.setIcon(this.defaultIcons[iconType])
  119. }
  120. },
  121. /**
  122. * 初始化checkbox值
  123. */
  124. initCheckGroup (data) {
  125. data.forEach((item) => {
  126. this.checkedMarkerLayerKey.push(item.poiType)
  127. this.markerLayerKeys.push({
  128. name: item.poiName,
  129. poiType: item.poiType
  130. })
  131. })
  132. },
  133. /**
  134. * 图层勾选
  135. */
  136. checkGroupChange (val) {
  137. this.rootLayerGroup.clearLayers()
  138. val.forEach((item) => {
  139. this.rootLayerGroup.addLayer(this.layersObj[item])
  140. })
  141. }
  142. }
  143. }
  144. </script>
  145. <style scoped lang='scss'>
  146. .map-2d {
  147. height: 100%;
  148. position: relative;
  149. .map2d-container {
  150. height: 100%;
  151. }
  152. .markerLayer-control {
  153. position: absolute;
  154. top: 0;
  155. left: 50%;
  156. transform: translateX(-50%);
  157. z-index: 999;
  158. }
  159. }
  160. </style>

       

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/234843
推荐阅读
相关标签
  

闽ICP备14008679号