基于gmap-vue的Vue/Nuxt项目:保存绘制图形数据、加载并编辑GeoJSON及坐标获取问题
解决gmap-vue绘图管理器的图形数据获取与GeoJSON加载编辑问题
我来帮你搞定这两个问题,结合gmap-vue(vue-google-maps分支)的特性和Google Maps原生API来处理:
1. 获取地图图形数据并生成GeoJSON
你看到的{__ob__: Observer}是Vue的响应式包装对象,overlay是一个getter属性,直接访问就能拿到对应的Google Maps原生图形对象(比如google.maps.Polygon、google.maps.Polyline等)。要提取坐标,需要调用这些原生对象的API方法,不同类型的图形获取坐标的方式不同,下面是完善后的代码:
let shapes = []; // 用Object.values遍历更直观 for (const shape of Object.values(this.shapes)) { const overlay = shape.overlay; // 直接获取原生Google Maps图形对象 let coordinates; let geometryType = shape.type.charAt(0).toUpperCase() + shape.type.slice(1); // 首字母大写匹配GeoJSON类型 switch (shape.type.toLowerCase()) { case 'polygon': // 多边形:getPaths()返回路径集合,转成GeoJSON的二维坐标数组 coordinates = overlay.getPaths().getArray().map(path => path.getArray().map(latLng => [latLng.lng(), latLng.lat()]) // GeoJSON是[lon, lat],和Google Maps的[lat, lon]相反 ); break; case 'polyline': // 折线:getPath()返回单条路径,转成一维坐标数组 coordinates = overlay.getPath().getArray().map(latLng => [latLng.lng(), latLng.lat()]); break; case 'rectangle': // 矩形:通过getBounds()获取西南/东北点,转成多边形的闭合坐标 const bounds = overlay.getBounds(); const sw = bounds.getSouthWest(); const ne = bounds.getNorthEast(); coordinates = [ [ [sw.lng(), sw.lat()], [ne.lng(), sw.lat()], [ne.lng(), ne.lat()], [sw.lng(), ne.lat()], [sw.lng(), sw.lat()] // 闭合路径 ] ]; break; case 'circle': // GeoJSON无原生Circle类型,用Point类型+properties存储半径 const center = overlay.getCenter(); coordinates = [center.lng(), center.lat()]; geometryType = 'Point'; // 覆盖类型为Point break; default: coordinates = []; } const tmp = { "type": "Feature", "properties": { "id": shape.id || null, "zIndex": shape.zIndex || null, // 如果是圆形,额外存储半径属性 ...(shape.type.toLowerCase() === 'circle' ? { radius: overlay.getRadius() } : {}) }, "geometry": { "type": geometryType, "coordinates": coordinates } }; shapes.push(tmp); } console.log(JSON.stringify(shapes, null, 2));
关键说明:
- Google Maps的
LatLng对象是(纬度, 经度),而GeoJSON坐标是[经度, 纬度],所以转换时要调换顺序 - 圆形在GeoJSON中没有标准类型,这里用
Point类型结合properties.radius来存储,后续加载时可以还原成Circle - Vue的响应式包装不会影响你直接访问
overlay属性,直接取值即可
2. 加载GeoJSON并支持编辑
要加载GeoJSON并让绘图管理器识别可编辑,需要把GeoJSON解析成Google Maps原生图形对象,再添加到this.shapes数组中(绘图管理器会监听这个数组的变化)。示例代码如下:
// 假设你的GeoJSON数据存储在geoJson变量中 function loadGeoJsonToMap(geoJson) { // 确保Google Maps API已加载完成 if (!window.google?.maps) return; geoJson.features.forEach(feature => { const geometry = feature.geometry; let overlay; let shapeType; switch (geometry.type) { case 'Polygon': // 判断是否是矩形(闭合的5个点) if (geometry.coordinates[0].length === 5) { // 转成Rectangle对象 const coords = geometry.coordinates[0]; const sw = new window.google.maps.LatLng(coords[0][1], coords[0][0]); const ne = new window.google.maps.LatLng(coords[2][1], coords[2][0]); const bounds = new window.google.maps.LatLngBounds(sw, ne); overlay = new window.google.maps.Rectangle({ bounds }); shapeType = 'rectangle'; } else { // 普通多边形 const paths = geometry.coordinates.map(path => path.map(coord => new window.google.maps.LatLng(coord[1], coord[0])) ); overlay = new window.google.maps.Polygon({ paths }); shapeType = 'polygon'; } break; case 'LineString': // 折线 const path = geometry.coordinates.map(coord => new window.google.maps.LatLng(coord[1], coord[0])); overlay = new window.google.maps.Polyline({ path }); shapeType = 'polyline'; break; case 'Point': // 还原圆形(如果有radius属性) const center = new window.google.maps.LatLng(geometry.coordinates[1], geometry.coordinates[0]); const radius = feature.properties.radius || 0; overlay = new window.google.maps.Circle({ center, radius }); shapeType = 'circle'; break; default: return; // 不支持的类型跳过 } // 添加到shapes数组,绘图管理器会自动识别并允许编辑 this.shapes.push({ overlay, type: shapeType, id: feature.properties.id || null, zIndex: feature.properties.zIndex || null }); }); } // 在合适的时机调用(比如mounted钩子,确保地图已初始化) // loadGeoJsonToMap(yourGeoJsonData);
关键说明:
- 加载前要确保Google Maps JS API已完全加载,避免
google对象未定义 - 同样要注意GeoJSON坐标和Google Maps
LatLng的顺序转换 - 矩形在GeoJSON中通常用Polygon表示,这里通过坐标点数量判断并还原成Rectangle对象,保持编辑体验一致
- 添加到
this.shapes后,绘图管理器会自动把这些图形渲染到地图上,并支持拖拽、编辑顶点等操作
内容的提问来源于stack exchange,提问作者nontechguy
相关产品推荐
相关产品推荐

