赞
踩
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.css,https://iclient.supermap.io/dist/leaflet/iclient-leaflet.min.css,这两个下载链接在官方都有,下载完成在html页面中引入即可。插件引入完成后进行地图的初始化,代码如下:
- initMap () {
- const host = window.isLocal
- ? window.server
- : 'https://iserver.supermap.io'
- const url = host + '/iserver/services/map-china400/rest/maps/China'
- this.mapObj = L.map(this.mapId, {
- // center: [0, 0],
- center: [45.7413805110411, 127.165046475283],
- maxZoom: 18,
- zoom: 6,
- zoomControl: false
- })
- L.supermap.tiledMapLayer(url).addTo(this.mapObj)
- this.rootLayerGroup = L.featureGroup().addTo(this.mapObj) // 添加根图层(方便管理其他图层)
- },
然后再mounted中调用,如下:
- mounted () {
- this.$nextTick(() => {
- this.initMap()
- })
- },
创建icon对象
在项目中,marker的种类不一,每种marker对应一个图标,因此需要的icon也就不一,加上marker点击高亮的icon,就需要为每个类型的mrker准备两个icon对象,一个默认,一个高亮,这里用两个对象defaultIcons和focusIcons分别保存默认图标和高亮图标(两个对象实际是两个map结构,以类型为key,对应的icon为value)。具体需要几种marker以后台数据为准,这里有一个json文件模拟数据:
- {
- "code": 200,
- "data": [
- {
- "id": 1,
- "lat": "",
- "lng": "",
- "poiName": "桥梁",
- "poiType": "bridge",
- "children": [
- {
- "id": 2,
- "lat": 44.9255,
- "lng": 127.2017,
- "poiName": "佳木斯大桥",
- "poiType": "bridge"
- },
- {
- "id": 3,
- "lat": 45.7933,
- "lng": 128.6749,
- "poiName": "佳木斯中桥",
- "poiType": "bridge"
- },
- {
- "id": 4,
- "lat": 44.9194,
- "lng": 128.5764,
- "poiName": "佳木斯小桥",
- "poiType": "bridge"
- },
- {
- "id": 12,
- "lat": 46.500976,
- "lng": 125.049838,
- "poiName": "桥A",
- "poiType": "bridge"
- },
- {
- "id": 13,
- "lat": 46.11039,
- "lng": 125.305188,
- "poiName": "桥B",
- "poiType": "bridge"
- },
- {
- "id": 14,
- "lat": 46.657439,
- "lng": 125.026459,
- "poiName": "桥C",
- "poiType": "bridge"
- },
- {
- "id": 15,
- "lat": 47.744832,
- "lng": 128.859247,
- "poiName": "桥D",
- "poiType": "bridge"
- },
- {
- "id": 16,
- "lat": 48.668639,
- "lng": 130.477707,
- "poiName": "桥E",
- "poiType": "bridge"
- },
- {
- "id": 17,
- "lat": 47.424955,
- "lng": 124.107461,
- "poiName": "桥F",
- "poiType": "bridge"
- },
- {
- "id": 18,
- "lat": 47.39034,
- "lng": 123.920893,
- "poiName": "桥G",
- "poiType": "bridge"
- }
- ]
- },
- {
- "id": 5,
- "lat": "",
- "lng": "",
- "poiName": "涵洞",
- "poiType": "culvert",
- "children": [
- {
- "id": 6,
- "lat": 45.7404,
- "lng": 127.1621,
- "poiName": "涵洞1",
- "poiType": "culvert"
- },
- {
- "id": 7,
- "lat": 45.44,
- "lng": 126.41,
- "poiName": "涵洞2",
- "poiType": "culvert"
- },
- {
- "id": 8,
- "lat": 45.73832834,
- "lng": 127.1584935,
- "poiName": "涵洞3",
- "poiType": "culvert"
- },
- {
- "id": 19,
- "lat": 44.599933,
- "lng": 129.616987,
- "poiName": "隧道A",
- "poiType": "culvert"
- }
- ]
- },
- {
- "id": 9,
- "lat": "",
- "lng": "",
- "poiName": "标志",
- "poiType": "trafficSafe",
- "children": [
- {
- "id": 10,
- "lat": 45.74045209,
- "lng": 127.1617092,
- "poiName": "指示标志",
- "poiType": "trafficSafe"
- },
- {
- "poiName": "交通路牌",
- "poiType": "trafficSafe",
- "lat": 45.74045209,
- "lng": 128.1617843,
- "id": 11
- }
- ]
- }
- ]
- }
可以看到这里的数据是一个树状结构,总共有3中marker(父节点的个数),为了方便将图片命名为对应的type,如图:
获取数据后初始化icon,代码如下:
- async getData () {
- const dataRes = await axios.get('/static/json/elTreeData.json')
- if (dataRes) {
- const treeData = dataRes.data.data
- this.setIcons(treeData)
- }
- },
- /**
- * 初始化Icons
- */
- setIcons (data) {
- data.forEach((item) => {
- this.defaultIcons[item.poiType] = L.icon({
- iconUrl: '/static/images/' + item.poiType + 'DefaultIcon.png',
- iconSize: [48, 60],
- iconAnchor: [24, 60],
- popupAnchor: [0, -30]
- })
- this.focusIcons[item.poiType] = L.icon({
- iconUrl: '/static/images/' + item.poiType + 'FocusIcon.png',
- iconSize: [48, 60],
- iconAnchor: [24, 60],
- popupAnchor: [0, -30]
- })
- })
- },
创建marker图层以及marker点
创建marker的时候需要点聚合,点聚合使用的是leaflet的插件leaflet.markercluster,具体使用方法参照官方,官网地址https://github.com/Leaflet/Leaflet.markercluster,创建marker代码如下:
- initMarkers (data) {
- data.forEach((item) => {
- // marker聚合 markerClusterGroup本质是一个图层,类似fetureGroup
- const markerLayer = L.markerClusterGroup({
- spiderfyOnMaxZoom: false,
- showCoverageOnHover: false,
- zoomToBoundsOnClick: false
- })
- item.children.forEach((item1) => {
- const marker = L.marker([item1.lat, item1.lng], {
- icon: this.defaultIcons[item1.poiType],
- markerId: item1.id,
- type: item1.poiType
- }).on('click', (ev) => {
- this.resetMarker()
- ev.target.setIcon(this.focusIcons[ev.target.options.type])
- this.focusMaker = ev.target
- })
- markerLayer.addLayer(marker)
- })
- this.rootLayerGroup.addLayer(markerLayer) // 将markerLayer添加到根图层
- })
- },
- /**
- * 将上一次点击marker的重置为默认图标
- */
- resetMarker () {
- if (this.focusMaker) {
- const iconType = this.focusMaker.options.type
- this.focusMaker.setIcon(this.defaultIcons[iconType])
- }
- }
添加图层切换功能
图层切换是利用了layerGroup的addLayer() 和 clearLayers()方法, 主要代码如下:
- /**
- * 初始化checkbox值
- */
- initCheckGroup (data) {
- data.forEach((item) => {
- this.checkedMarkerLayerKey.push(item.poiType)
- this.markerLayerKeys.push({
- name: item.poiName,
- poiType: item.poiType
- })
- })
- },
- /**
- * 图层勾选
- */
- checkGroupChange (val) {
- this.rootLayerGroup.clearLayers()
- val.forEach((item) => {
- this.rootLayerGroup.addLayer(this.layersObj[item])
- })
- }
最终实现效果:
本篇文章作为本人实际项目的参考、复制、粘贴来源,因此有些细节并未提及。最后附上地图vue文件的完整代码。
mapVue完整代码
- <template>
- <div class="map-2d">
- <div class="markerLayer-control">
- <el-checkbox-group
- v-model="checkedMarkerLayerKey"
- @change="checkGroupChange"
- >
- <el-checkbox
- v-for="item in markerLayerKeys"
- :key="item.poiType"
- :label="item.poiType"
- >
- {{ item.name }}
- </el-checkbox>
- </el-checkbox-group>
- </div>
- <div class="map2d-container" :id="mapId"></div>
- </div>
- </template>
- <script>
- import 'leaflet.markercluster/dist/MarkerCluster.css'
- import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
- import 'leaflet.markercluster'
- import axios from 'axios'
- export default {
- data () {
- return {
- mapId: 'map2d', // 地图id
- mapObj: null, // 地图对象
- rootLayerGroup: null, // 根图层
- checkedMarkerLayerKey: [], // 图层勾选值-checkbox-group绑定值
- markerLayerKeys: [], // 图层类型-给checkbox用
- defaultIcons: {}, // 默认图标
- focusIcons: {}, // 高亮图标
- layersObj: {} // 存放markerLayer图层,便于图层切换
- }
- },
- mounted () {
- this.$nextTick(() => {
- this.initMap()
- })
- },
- methods: {
- initMap () {
- const host = window.isLocal
- ? window.server
- : 'https://iserver.supermap.io'
- const url = host + '/iserver/services/map-china400/rest/maps/China'
- this.mapObj = L.map(this.mapId, {
- // center: [0, 0],
- center: [45.7413805110411, 127.165046475283],
- maxZoom: 18,
- zoom: 6,
- zoomControl: false
- })
- L.supermap.tiledMapLayer(url).addTo(this.mapObj)
- this.rootLayerGroup = L.featureGroup().addTo(this.mapObj) // 添加根图层(方便管理其他图层)
- this.getData()
- },
- async getData () {
- const dataRes = await axios.get('/static/json/elTreeData.json')
- if (dataRes) {
- const treeData = dataRes.data.data
- this.setIcons(treeData)
- this.initMarkers(treeData)
- this.initCheckGroup(treeData)
- }
- },
- /**
- * 初始化Icons
- */
- setIcons (data) {
- data.forEach((item) => {
- this.defaultIcons[item.poiType] = L.icon({
- iconUrl: '/static/images/' + item.poiType + 'DefaultIcon.png',
- iconSize: [48, 60],
- iconAnchor: [24, 60],
- popupAnchor: [0, -30]
- })
- this.focusIcons[item.poiType] = L.icon({
- iconUrl: '/static/images/' + item.poiType + 'FocusIcon.png',
- iconSize: [48, 60],
- iconAnchor: [24, 60],
- popupAnchor: [0, -30]
- })
- })
- },
- initMarkers (data) {
- data.forEach((item) => {
- // marker聚合 markerClusterGroup本质是一个图层,类似fetureGroup
- const markerLayer = L.markerClusterGroup({
- spiderfyOnMaxZoom: false,
- showCoverageOnHover: false,
- zoomToBoundsOnClick: false
- })
- item.children.forEach((item1) => {
- const marker = L.marker([item1.lat, item1.lng], {
- icon: this.defaultIcons[item1.poiType],
- markerId: item1.id,
- type: item1.poiType
- }).on('click', (ev) => {
- this.resetMarker()
- ev.target.setIcon(this.focusIcons[ev.target.options.type])
- this.focusMaker = ev.target
- })
- markerLayer.addLayer(marker)
- })
- this.layersObj[item.poiType] = markerLayer
- this.rootLayerGroup.addLayer(markerLayer) // 将markerLayer添加到根图层
- })
- },
- /**
- * 将上一次点击marker的重置为默认图标
- */
- resetMarker () {
- if (this.focusMaker) {
- const iconType = this.focusMaker.options.type
- this.focusMaker.setIcon(this.defaultIcons[iconType])
- }
- },
- /**
- * 初始化checkbox值
- */
- initCheckGroup (data) {
- data.forEach((item) => {
- this.checkedMarkerLayerKey.push(item.poiType)
- this.markerLayerKeys.push({
- name: item.poiName,
- poiType: item.poiType
- })
- })
- },
- /**
- * 图层勾选
- */
- checkGroupChange (val) {
- this.rootLayerGroup.clearLayers()
- val.forEach((item) => {
- this.rootLayerGroup.addLayer(this.layersObj[item])
- })
- }
- }
- }
- </script>
- <style scoped lang='scss'>
- .map-2d {
- height: 100%;
- position: relative;
- .map2d-container {
- height: 100%;
- }
- .markerLayer-control {
- position: absolute;
- top: 0;
- left: 50%;
- transform: translateX(-50%);
- z-index: 999;
- }
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。