从Thomas的答案开始,这里提供了一种实现方式,可以编辑使用DrawingManager
创建的覆盖物,以及从GeoJSON添加的Feature
s。
对我来说,主要的挑战是在DrawingManager
创建的带有google.maps
前缀的覆盖物类型和使用addFromGeoJson()
创建的同名google.maps.Data
Feature
类型之间进行区分。最终,我放弃了内置的Data
对象,而是将所有内容都作为重新创建的覆盖物进行存储,并设置编辑事件监听器,然后在绘制它们时逐个调用setMap()
。最初绘制的覆盖物和加载的要素被丢弃。
该过程大致如下:
- 初始化地图。
- 添加
addfeature
事件监听器以检测何时添加要素。这将在addGeoJson()
期间为每个Feature
触发,获取其相应的覆盖类型和几何形状,并将它们传递给实用函数addFeature()
来创建覆盖。
- 加载任何GeoJSON。这将为每个加载的对象触发上面的事件监听器。
- 初始化
DrawingManager
。
- 为每种类型的覆盖物(
polygon
、polyline
和marker
)添加{overlay}complete
事件侦听器。当触发时,这些事件首先确定覆盖物是否有效(例如,多边形具有>= 3个顶点),然后调用addFeature()
,传入覆盖类型和几何形状。
调用addFeature()
时,会重新创建覆盖物并设置所有适用的事件监听器。最后,覆盖物存储在数组中并显示在地图上。
var imported = {
type: "FeatureCollection",
features: [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-73.985603, 40.748429
],
},
properties: {
activity: "Entry",
}
}, ]
};
var features = {
polygons: [],
lines: [],
markers: []
};
var styles = {
polygon: {
fillColor: '#00ff80',
fillOpacity: 0.3,
strokeColor: '#008840',
strokeWeight: 1,
clickable: true,
editable: true,
zIndex: 1
},
polyline: {
strokeColor: '#ffff00',
strokeWeight: 3,
clickable: true,
editable: true,
zIndex: 2
},
marker: {
clickable: true,
draggable: true,
zIndex: 3
}
}
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 40.748429,
lng: -73.985603
},
zoom: 18,
noClear: true,
mapTypeId: 'satellite',
navigationControl: true,
mapTypeControl: false,
streetViewControl: false,
tilt: 0
});
map.data.addListener('addfeature', featureAdded);
map.data.addGeoJson(imported);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: ['polygon', 'polyline', 'marker']
},
polygonOptions: styles.polygon,
polylineOptions: styles.polyline,
markerOptions: styles.marker
});
drawingManager.setMap(map);
drawingManager.addListener('polygoncomplete', function(polygon) {
if (polygon.getPath().getLength() < 3) {
alert('Polygons must have 3 or more points.');
polygon.getPath().clear();
}
else {
addFeature('Polygon', polygon.getPath());
polygon.setMap(null);
}
});
drawingManager.addListener('polylinecomplete', function(line) {
if (line.getPath().getLength() < 2) {
alert('Lines must have 2 or more points.');
line.getPath().clear();
}
else {
addFeature('Polyline', line.getPath());
line.setMap(null);
}
});
drawingManager.addListener('markercomplete', function(marker) {
addFeature('Point', marker.getPosition());
marker.setMap(null);
updateGeoJSON();
});
}
function featureAdded(e) {
switch (e.feature.getGeometry().getType()) {
case 'Polygon':
addFeature('Polygon', e.feature.getGeometry().getAt(0).getArray());
break;
case 'LineString':
addFeature('Polyline', e.feature.getGeometry().getArray());
break;
case 'Point':
addFeature('Point', e.feature.getGeometry().get());
}
map.data.remove(e.feature);
}
function addFeature(type, path) {
switch (type) {
case 'Polygon':
var polygon = new google.maps.Polygon(styles.polygon);
polygon.setPath(path);
polygon.getPath().addListener('insert_at', someFunction)
polygon.getPath().addListener('set_at', someFunction);
polygon.getPath().addListener('remove_at', someFunction);
polygon.getPath().addListener('dragend', someFunction);
polygon.addListener('rightclick', function(e) {
if (e.vertex == undefined) return;
if (polygon.getPath().getLength() == 3) {
polygon.setMap(null);
features.polygons = features.polygons.filter(isValid);
} else {
polygon.getPath().removeAt(e.vertex);
outputAsGeoJSON();
}
});
features.polygons.push(polygon);
polygon.setMap(map);
break;
case 'Polyline':
var line = new google.maps.Polyline(styles.polyline);
line.setPath(path);
line.getPath().addListener('insert_at', someOtherFunction);
line.getPath().addListener('set_at', someOtherFunction);
line.getPath().addListener('remove_at', someOtherFunction);
line.getPath().addListener('dragend', someOtherFunction);
line.addListener('rightclick', function(e) {
if (e.vertex == undefined) return;
if (line.getPath().getLength() == 2) {
line.setMap(null);
features.lines = features.lines.filter(isValid);
} else {
line.getPath().removeAt(e.vertex);
outputAsGeoJSON();
}
});
features.lines.push(line);
line.setMap(map);
break;
case 'Point':
var marker = new google.maps.Marker(styles.marker);
marker.setPosition(path);
marker.setAnimation(google.maps.Animation.DROP);
marker.addListener('drag', function(e) {
marker.setAnimation(google.maps.Animation.BOUNCE);
});
marker.addListener('dragend', function(e) {
marker.setAnimation(null);
})
marker.addListener('rightclick', function(e) {
marker.setMap(null);
features.markers = features.markers.filter(isValid);
outputAsGeoJSON();
});
features.markers.push(marker);
marker.setMap(map);
break;
}
outputAsGeoJSON();
}
function someFunction() {
}
function someOtherFunction() {
}
function isValid(f) {
return f.getMap() != null;
}
function outputAsGeoJSON() {
var data = new google.maps.Data;
features.polygons.forEach(function(polygon, i) {
data.add({
geometry: new google.maps.Data.Polygon([polygon.getPath().getArray()]),
properties: {
description: 'I am a polygon'
}
});
});
features.lines.forEach(function(line, i) {
data.add({
geometry: new google.maps.Data.LineString(line.getPath().getArray()),
properties: {
description: 'I am a line'
}
});
});
features.markers.forEach(function(marker, i) {
data.add({
geometry: new google.maps.Data.Point(marker.getPosition()),
properties: {
description: 'I am a marker'
}
});
});
data.toGeoJson(function(json) {
document.getElementById('geojson').value = JSON.stringify(json);
});
}
https://jsfiddle.net/pqdu05s9/1/
{overlay}complete
事件监听器中就解决了问题。 - Erich