【问题标题】:How to save a Google maps overlay shape in the database?如何在数据库中保存 Google 地图叠加形状?
【发布时间】:2013-11-06 01:05:13
【问题描述】:

我想在数据库中保存一个 Google 地图叠加形状。这是我的代码。它工作得很好,但我只需要在数据库中保存all_shapes 数组。

<html>
<head>

<style type="text/css">
  #map, html, body
  {
      padding: 0;
      margin: 0;
      height: 100%;
  }
</style>

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&libraries=drawing,geometry"></script>

<script>
var coordinates = [];
var all_shapes = [];

var selectedShape;
</script>

<script>
function draw_shape()
{
    for(var i = 0; i < all_shapes.length; i++)
    {
        all_shapes[i].setMap(null);
    }

    for(var i = 0; i < all_shapes.length; i++)
    {
        all_shapes[i].setMap(map);
    }
}
</script>

<script>
function clearSelection()
{
    if(selectedShape)
    {
        selectedShape.setEditable(false);
        selectedShape = null;
    }
}

function setSelection(shape)
{
    clearSelection();
    selectedShape = shape;
    shape.setEditable(true);
}

function deleteSelectedShape()
{
    if (selectedShape)
    {
        selectedShape.setMap(null);
    }
}
</script>

<script>
function save_coordinates_to_array(newShapeArg)
{
    if(newShapeArg.type == google.maps.drawing.OverlayType.POLYGON)
    {
        var polygonBounds = newShapeArg.getPath();

        for(var i = 0 ; i < polygonBounds.length ; i++)
        {
            coordinates.push(polygonBounds.getAt(i).lat(), polygonBounds.getAt(i).lng());
        }
    }
    else
    {
        //alert("Not polygon");/////////////
    }   
}
</script>

<script>
var map;

function initialize()
{
    map = new google.maps.Map(document.getElementById('map'), {zoom: 12, center: new google.maps.LatLng(32.344, 51.048)});

    var drawingManager = new google.maps.drawing.DrawingManager();
    drawingManager.setMap(map);

    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
        var newShape = e.overlay;
        newShape.type = e.type;

        all_shapes.push(newShape);

        setSelection(newShape);

        save_coordinates_to_array(newShape);

        google.maps.event.addListener(newShape, 'click', function() {setSelection(newShape)});
      });

    google.maps.event.addListener(map, 'click', function(e) {clearSelection();});
}

google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>

<body>
<table border="1">
  <tr>
    <td>Name</td>
    <td><input name="name" id="name" type="text"></td>
  </tr>
  <tr>
    <td>Color</td>
    <td>
      <table border="1" width="100%">
        <tr>
          <td bgcolor="#FF0000">&nbsp;</td>
          <td bgcolor="#00FF00">&nbsp;</td>
          <td bgcolor="#0000FF">&nbsp;</td>
        </tr>
      </table>
    </td>
  </tr>
  <tr>
    <td colspan="2"><input name="save" type="button" value="Save" onClick="draw_shape()"></td>
  </tr>
  <tr>
    <td colspan="2"><input name="delete" type="button" value="Delete" onClick="deleteSelectedShape()"></td>
  </tr>  
</table>

<div id="map"></div>
</body>

</html>

在哪里以及如何将创建的叠加形状保存在数据库中。所有形状都保存在var all_shapes = []; 数组中。我必须为数据库中的字段选择哪种类型?我的意思是例如 int、char 等。 我将使用 MySQL 和 PHP。

【问题讨论】:

标签: mysql database google-maps-api-3 shapes overlays


【解决方案1】:

当您只是想以某种方式存储形状时,您可以使用 JSON 字符串,将其存储在例如Text-column(char 对于存储详细的多边形/折线来说太小了)

注意:当你创建 JSON 字符串时,你必须转换属性(例如转换为原生数组或对象),你不能直接存储例如 LatLng 的,因为保存时原型会丢失。折线/多边形的路径可以存储encoded

另一种方法: 使用多个列,例如

  1. 存储类型(LatLng、Circle、Polyline 等)的列(varchar
  2. 一列 (geometry) 用于存储几何特征(LatLng、多边形或折线)
  3. 存储半径的列(int)(插入圆时使用)
  4. 可选的列(text)存储样式选项(需要时)

当您只想存储它时,第一个建议就足够了。

当您必须能够选择特定形状时,例如对于给定区域,请使用第二个建议。 有关空间扩展的详细信息,请参阅http://dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html


2 个函数,它们要么删除循环引用并创建可存储对象,要么从这些存储对象中恢复覆盖。

var IO={
  //returns array with storable google.maps.Overlay-definitions
  IN:function(arr,//array with google.maps.Overlays
              encoded//boolean indicating if pathes should be stored encoded
              ){
      var shapes     = [],
          goo=google.maps,
          shape,tmp;

      for(var i = 0; i < arr.length; i++)
      {   
        shape=arr[i];
        tmp={type:this.t_(shape.type),id:shape.id||null};


        switch(tmp.type){
           case 'CIRCLE':
              tmp.radius=shape.getRadius();
              tmp.geometry=this.p_(shape.getCenter());
            break;
           case 'MARKER': 
              tmp.geometry=this.p_(shape.getPosition());   
            break;  
           case 'RECTANGLE': 
              tmp.geometry=this.b_(shape.getBounds()); 
             break;   
           case 'POLYLINE': 
              tmp.geometry=this.l_(shape.getPath(),encoded);
             break;   
           case 'POLYGON': 
              tmp.geometry=this.m_(shape.getPaths(),encoded);

             break;   
       }
       shapes.push(tmp);
    }

    return shapes;
  },
  //returns array with google.maps.Overlays
  OUT:function(arr,//array containg the stored shape-definitions
               map//map where to draw the shapes
               ){
      var shapes     = [],
          goo=google.maps,
          map=map||null,
          shape,tmp;

      for(var i = 0; i < arr.length; i++)
      {   
        shape=arr[i];       

        switch(shape.type){
           case 'CIRCLE':
             tmp=new goo.Circle({radius:Number(shape.radius),
                                  center:this.pp_.apply(this,shape.geometry)});
            break;
           case 'MARKER': 
             tmp=new goo.Marker({position:this.pp_.apply(this,shape.geometry)});
            break;  
           case 'RECTANGLE': 
             tmp=new goo.Rectangle({bounds:this.bb_.apply(this,shape.geometry)});
             break;   
           case 'POLYLINE': 
             tmp=new goo.Polyline({path:this.ll_(shape.geometry)});
             break;   
           case 'POLYGON': 
             tmp=new goo.Polygon({paths:this.mm_(shape.geometry)});

             break;   
       }
       tmp.setValues({map:map,id:shape.id})
       shapes.push(tmp);
    }
    return shapes;
  },
  l_:function(path,e){
    path=(path.getArray)?path.getArray():path;
    if(e){
      return google.maps.geometry.encoding.encodePath(path);
    }else{
      var r=[];
      for(var i=0;i<path.length;++i){
        r.push(this.p_(path[i]));
      }
      return r;
    }
  },
  ll_:function(path){
    if(typeof path==='string'){
      return google.maps.geometry.encoding.decodePath(path);
    }
    else{
      var r=[];
      for(var i=0;i<path.length;++i){
        r.push(this.pp_.apply(this,path[i]));
      }
      return r;
    }
  },

  m_:function(paths,e){
    var r=[];
    paths=(paths.getArray)?paths.getArray():paths;
    for(var i=0;i<paths.length;++i){
        r.push(this.l_(paths[i],e));
      }
     return r;
  },
  mm_:function(paths){
    var r=[];
    for(var i=0;i<paths.length;++i){
        r.push(this.ll_.call(this,paths[i]));

      }
     return r;
  },
  p_:function(latLng){
    return([latLng.lat(),latLng.lng()]);
  },
  pp_:function(lat,lng){
    return new google.maps.LatLng(lat,lng);
  },
  b_:function(bounds){
    return([this.p_(bounds.getSouthWest()),
            this.p_(bounds.getNorthEast())]);
  },
  bb_:function(sw,ne){
    return new google.maps.LatLngBounds(this.pp_.apply(this,sw),
                                        this.pp_.apply(this,ne));
  },
  t_:function(s){
    var t=['CIRCLE','MARKER','RECTANGLE','POLYLINE','POLYGON'];
    for(var i=0;i<t.length;++i){
       if(s===google.maps.drawing.OverlayType[t[i]]){
         return t[i];
       }
    }
  }

}

IO.IN 返回的数组可能会被发送到服务器端脚本。服务器端脚本应该遍历这个数组并将一个 JSON 字符串插入到表中:

<?php
$mysqli = new mysqli(/*args*/);
$stmt = $mysqli->prepare('INSERT INTO `tableName`(`columnName`) VALUES (?)');
$stmt->bind_param('s', $json);

foreach($_POST['shapes'] as $value){
  $json = json_encode($value);
  $stmt->execute();
}
?>

要恢复形状,请获取它们:

<?php
$json=array();
$res=$mysqli->query('SELECT `columnName` from `tableName`');
while ($row = $res->fetch_assoc()) {
        $json[]=json_decode($row['columnName']);
    }
$res->close();
$json=json_encode($json);
?>

并将结果传递给IO.OUT():

IO.OUT(<?php echo $json;?>, someGoogleMapsInstance);

演示:http://jsfiddle.net/doktormolle/EdZk4/show/

【讨论】:

  • 我对使用 JSON 方法很感兴趣,但存在循环引用。通过使用 JSON,我们只需要一列包含字符串。可以使用 JSON 吗?
  • 关于使用第二种方法来使用某些列。要保存多边形的所有点,我应该如何保存它?我的意思是我必须使用一个字符串列或大量的 int 列?
  • 我在上面添加了一些细节(与第一种方法有关)。第二种方法要复杂得多,我不确定接下来几天我是否有时间详细解释。但是要回答与列类型相关的问题:它是GEOMETRY,这种类型可以用来存储点、线和多边形,足以存储任何类型的google.maps.Overlay(CIRCLE除外,这里你需要半径的附加列)
  • 您的 JSON 方法非常完美!非常感谢!
  • @Dr.Molle 你能给我一些关于在 sqlite 数据库中保存 lat lng 点的建议吗?我正在开发一个 track-my-run 应用程序,现在我想知道是否应该将每个点保存为单独的行或收集数组中的所有点并存储数组?有什么想法吗?
【解决方案2】:

Simple GeoJson Editor 是在谷歌地图上绘制、编辑、删除和保存形状为 geoJson 的示例。作者(谷歌实习生)在post 中描述了这个项目。

JavascriptHTML 未缩小。

可以在Geojson.io找到更好的开源工具

【讨论】:

    【解决方案3】:

    我在代码http://jsfiddle.net/doktormolle/EdZk4/show/发现的奇怪行为
    我在 IN 函数中添加了下一个代码:

             if (tmp.type != 'MARKER') {
                 tmp.strokeColor = shape.strokeColor;
                 tmp.strokeWeight = shape.strokeWeight;
                 tmp.fillColor = shape.fillColor;
                 tmp.fillOpacity = shape.fillOpacity;
                 tmp.editable = shape.getEditable();
                 if (tmp.type == 'POLYLINE' || tmp.type == 'POLYGON')
                     tmp.infoWindowContent = shape.infoWindow.content;
             }
    

    所有形状都是可编辑的,但只有最后一个显示可编辑为真。例如,我添加了一条可编辑的折线,它在结果中是可编辑的。

        "[{"type":"POLYLINE","id":null,"draggable":false,"geometry":["gn_sFwt`eEvmd@ig|B"],
    "strokeColor":"red","strokeWeight":3,"fillOpacity":0.35,"editable":true,
    "infoWindowContent":"Polyline Length: 58.80  kms"}]"
    

    我添加了第二条可编辑多段线,但结果第一条不可编辑,第二条可编辑。

        "[{"type":"POLYLINE","id":null,"draggable":false,"geometry":["gn_sFwt`eEvmd@ig|B"],
    "strokeColor":"red","strokeWeight":3,"fillOpacity":0.35,"editable":false,
    "infoWindowContent":"Polyline Length: 58.80  kms"},
        {"type":"POLYLINE","id":null,"draggable":false,"geometry":["qoiqFgvheEcsw@ygz@"],
    "strokeColor":"red","strokeWeight":3,"fillOpacity":0.35,"editable":true,
    "infoWindowContent":"Polyline Length: 41.41  kms"}]"
    

    【讨论】:

      【解决方案4】:

      如果您需要存储路径只是为了稍后在地图上恢复它,您也可以使用Google Maps Encoding Utility。它没有 Dr.Molle 的答案那么强大,但对于存储多边形和折线很有用。

      【讨论】:

        猜你喜欢
        • 2014-04-16
        • 1970-01-01
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        • 2016-10-30
        • 1970-01-01
        • 2023-03-22
        • 2013-09-24
        相关资源
        最近更新 更多