I want to save a Google maps overlay shape in the database. This is my code. It works perfectly but I just need to save all_shapes
array in the database.
When you simply want to store the shapes somehow, you may use a JSON-string, store it in e.g. a Text
-column(char
would be to small to store detailed polygons/polylines )
Note: when you create the JSON-string, you must convert the properties(e.g. to native arrays or objects), you cannot store for example LatLng's directly, because the prototype will be lost when saving it. Pathes of polylines/polygons may be stored encoded
Another approach: use multiple columns, e.g.
varchar
) where you store the type(LatLng, Circle,Polyline,etc.)geometry
) where you store the geometric features(LatLng,Polygon or Polyline)int
) where you store a radius(used when you insert a circle)text
) where you store the style-options(when needed)The first suggestion would be sufficient when you simply want to store it.
When you must be able to select particular shapes, e.g for a given area, use the 2nd suggestion. See http://dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html for details of the spatial extensions
2 functions that either remove the circular references and create storable objects, or restore the overlays from these stored objects.
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];
}
}
}
}
The array returned by IO.IN
may be sended to a serverside script. The serverside script should iterate over this array and INSERT a JSON-string into the table:
<?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();
}
?>
to restore the shapes fetch them:
<?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);
?>
and pass the result to IO.OUT()
:
IO.OUT(<?php echo $json;?>, someGoogleMapsInstance);
Demo: http://jsfiddle.net/doktormolle/EdZk4/show/
Simple GeoJson Editor is an example of drawing, editing, dropping and saving shapes as geoJson on google maps. The author ( a Google intern) described the project in this post.
The Javascript and HTML are not minified.
An even better opensource tool can be found at Geojson.io
If you need to store the path just to restore it later on a map, you can also use Google Maps Encoding Utility. It is not as powerful as Dr.Molle's answer but can be useful for storing polygons and polylines.