目录

持久化存储 leaflet geoman 图层指南

Leaflet-Geoman 介绍

Leaflet-Geoman 是一个对 leaflet 的扩展或者说插件,可以让用户对 leaflet 对象进行自由编辑,包括了自由绘制、缩放旋转拖拽等等功能。

 

需求

在使用 leaflet-geoman 提供的绘制功能在地图上绘制一个 polygon 之后,需要将 polygon 持久化保存到数据库中,并允许重新加载以及再次进行编辑。

 

保存入库

要将整个 geoman 对象存入数据库是不现实的,因为如果在控制台打印一下就会发现它自身拥有的字段和属性非常多,即使在数据库中以 json 字段存储,也会产生过多数据。

https://wumanhoblogimg.obs.cn-south-1.myhuaweicloud.com/images/leaflet/consle.png

所以思路就是只保存关键信息,下次加载时再通过这些关键信息将图形重新加载出来。

简单版:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 /**
   * 生成用于保存到数据库的 geoJSON 数据
   * @returns featureCollection geoJSON
   */
  function generateGeoJson() {
    const fg = L.featureGroup()
    const layers = map.pm.getGeomanDrawLayers()
    layers.forEach(function (layer) {
      fg.addLayer(layer)
    })
    return fg.toGeoJSON()
  }

详细版:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function generateGeoJson() {
  var layers = findLayers(map)

  var geo = {
    type: 'FeatureCollection',
    features: []
  }
  layers.forEach(function (layer) {
    var geoJson = JSON.parse(JSON.stringify(layer.toGeoJSON()))
    if (!geoJson.properties) {
      geoJson.properties = {}
    }

    geoJson.properties.options = JSON.parse(JSON.stringify(layer.options))

    if (layer.options.radius) {
      var radius = parseFloat(layer.options.radius)
      if (radius % 1 !== 0) {
        geoJson.properties.options.radius = radius.toFixed(6)
      } else {
        geoJson.properties.options.radius = radius.toFixed(0)
      }
    }

    if (layer instanceof L.Rectangle) {
      geoJson.properties.type = 'rectangle'
    } else if (layer instanceof L.Circle) {
      geoJson.properties.type = 'circle'
    } else if (layer instanceof L.CircleMarker) {
      geoJson.properties.type = 'circlemarker'
    } else if (layer instanceof L.Polygon) {
      geoJson.properties.type = 'polygon'
    } else if (layer instanceof L.Polyline) {
      geoJson.properties.type = 'polyline'
    } else if (layer instanceof L.Marker) {
      geoJson.properties.type = 'marker'
    }

    geo.features.push(geoJson)
  })
  return geo
}

function findLayers(map) {
  let layers = []
  map.eachLayer((layer) => {
    if (
      layer instanceof L.Polyline ||
      layer instanceof L.Marker ||
      layer instanceof L.Circle ||
      layer instanceof L.CircleMarker
    ) {
      layers.push(layer)
    }
  })
  // 过滤没有 geoman 实例的图层
  layers = layers.filter((layer) => !!layer.pm)
  // 过滤没必要的临时数据
  layers = layers.filter((layer) => !layer._pmTempLayer)
  return layers
}

 

加载图层

加载方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function importGeoJSON(feature) {
  const geoLayer = L.geoJSON(feature, {
    style: function (feature) {
      return feature.properties.options
    },
    pointToLayer: function (feature, latlng) {
      switch (feature.properties.type) {
        case 'marker':
          return new L.Marker(latlng)
        case 'circle':
          return new L.Circle(latlng, feature.properties.options)
        case 'circlemarker':
          return new L.CircleMarker(latlng, feature.properties.options)
      }
    }
  })

  geoLayer.getLayers().forEach((layer) => {
    if (layer._latlng) {
      var latlng = layer.getLatLng()
    } else {
      var latlng = layer.getLatLngs()
    }
    switch (layer.feature.properties.type) {
      case 'rectangle':
        new L.Rectangle(latlng, layer.options).addTo(map)
        break
      case 'circle':
        console.log(layer.options)
        new L.Circle(latlng, layer.options).addTo(map)
        break
      case 'polygon':
        new L.Polygon(latlng, layer.options).addTo(map)
        break
      case 'polyline':
        new L.Polyline(latlng, layer.options).addTo(map)
        break
      case 'marker':
        new L.Marker(latlng, layer.options).addTo(map)
        break
      case 'circlemarker':
        new L.CircleMarker(latlng, layer.options).addTo(map)
        break
    }
  })
}

启用编辑:

1
2
3
4
5
 function editPolygon(layer) {
    layer.pm.enable({
      allowSelfIntersection: false   // 禁止交叉
    })
  }

 

(完)

参考

示例代码