In extension to my previous post on Dynamically Movable and Resizable Circle Overlay, I created yet another nifty tool to dynamically draw a polygon overlay on Google Maps. You won’t find another robust tool like this for Polygon drawing on the internet. Users can draw polygon dynamically by adding, deleting and moving the polygon boundary nodes. User can press shift+click on the map to add a new node to polygon boundary or they can press ctrl+click on any node marker to remove it. The node markers can be dragged around to resize the polygon.
This is how it looks like in action:
The JavaScript code is pretty easy to modify for your custom needs. The initialize() function is used to initialize the Google Map object when the page loads. A click event is also added to the map for adding node markers on the map. The click event takes care of the case when the user click on the previous markers while holding the shift key. When the user clicks on the map, addMarker() function is called to add another boundary node to the polygon. For every newly added marker, drag events are assigned for resizing the polygon and a click event is assigned to delete the node when ctrl key is pressed while clicking the marker pin. The fitPolygon() function is used to set map bounds and center to adjust the polygon inside it.
Put the following JavaScript code in the head section of your page:
<script type="text/javascript">
/* Developed by: Abhinay Rathore [web3o.blogspot.com] */
//Global variables
var global = this;
var map;
var PolygonMarkers = []; //Array for Map Markers
var PolygonPoints = []; //Array for Polygon Node Markers
var bounds = new GLatLngBounds; //Polygon Bounds
var Polygon; //Polygon overlay object
var polygon_resizing = false; //To track Polygon Resizing
//Polygon Marker/Node icons
var redpin = new GIcon(); //Red Pushpin Icon
redpin.image = "http://maps.google.com/mapfiles/ms/icons/red-pushpin.png";
redpin.iconSize = new GSize(32, 32);
redpin.iconAnchor = new GPoint(10, 32);
var bluepin = new GIcon(); //Blue Pushpin Icon
bluepin.image = "http://maps.google.com/mapfiles/ms/icons/blue-pushpin.png";
bluepin.iconSize = new GSize(32, 32);
bluepin.iconAnchor = new GPoint(10, 32);
function initialize() { //Initialize Google Map
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas")); //New GMap object
map.setCenter(new GLatLng(38.90, -94.68007), 13);
var ui = new GMapUIOptions(); //Map UI options
ui.maptypes = { normal:true, satellite:true, hybrid:true, physical:false }
ui.zoom = {scrollwheel:true, doubleclick:true};
ui.controls = { largemapcontrol3d:true, maptypecontrol:true, scalecontrol:true };
map.setUI(ui); //Set Map UI options
//Add Shift+Click event to add Polygon markers
GEvent.addListener(map, "click", function(overlay, point, overlaypoint) {
var p = (overlaypoint) ? overlaypoint : point;
//Add polygon marker if overlay is not an existing marker and shift key is pressed
if (global.shiftKey && !checkPolygonMarkers(overlay)) { addMarker(p); }
});
}
}
// Adds a new Polygon boundary marker
function addMarker(point) {
var markerOptions = { icon: bluepin, draggable: true };
var marker = new GMarker(point, markerOptions);
PolygonMarkers.push(marker); //Add marker to PolygonMarkers array
map.addOverlay(marker); //Add marker on the map
GEvent.addListener(marker,'dragstart',function(){ //Add drag start event
marker.setImage(redpin.image);
polygon_resizing = true;
});
GEvent.addListener(marker,'drag',function(){ drawPolygon(); }); //Add drag event
GEvent.addListener(marker,'dragend',function(){ //Add drag end event
marker.setImage(bluepin.image);
polygon_resizing = false;
drawPolygon();
fitPolygon();
});
GEvent.addListener(marker,'click',function(point) { //Add Ctrl+Click event to remove marker
if (global.ctrlKey) { removeMarker(point); }
});
drawPolygon();
//If more then 2 nodes then automatically fit the polygon
if(PolygonMarkers.length > 2) fitPolygon();
}
// Removes a Polygon boundary marker
function removeMarker(point) {
if(PolygonMarkers.length == 1){ //Only one marker in the array
map.removeOverlay(PolygonMarkers[0]);
map.removeOverlay(PolygonMarkers[0]);
PolygonMarkers = [];
if(Polygon){map.removeOverlay(Polygon)};
}
else //More then one marker
{
var RemoveIndex = -1;
var Remove;
//Search for clicked Marker in PolygonMarkers Array
for(var m=0; m<PolygonMarkers.length; m++)
{
if(PolygonMarkers[m].getPoint().equals(point))
{
RemoveIndex = m; Remove = PolygonMarkers[m]
break;
}
}
//Shift Array elemeents to left
for(var n=RemoveIndex; n<PolygonMarkers.length-1; n++)
{
PolygonMarkers[n] = PolygonMarkers[n+1];
}
PolygonMarkers.length = PolygonMarkers.length-1 //Decrease Array length by 1
map.removeOverlay(Remove); //Remove Marker
drawPolygon(); //Redraw Polygon
}
}
//Draw Polygon from the PolygonMarkers Array
function drawPolygon()
{
PolygonPoints.length=0;
for(var m=0; m<PolygonMarkers.length; m++)
{
PolygonPoints.push(PolygonMarkers[m].getPoint()); //Add Markers to PolygonPoints node array
}
//Add first marker in the end to close the Polygon
PolygonPoints.push(PolygonMarkers[0].getPoint());
if(Polygon){ map.removeOverlay(Polygon); } //Remove existing Polygon from Map
var fillColor = (polygon_resizing) ? 'red' : 'blue'; //Set Polygon Fill Color
Polygon = new GPolygon(PolygonPoints, '#FF0000', 2, 1, fillColor, 0.2); //New GPolygon object
map.addOverlay(Polygon); //Add Polygon to the Map
//TO DO: Function Call triggered after Polygon is drawn
}
//Fits the Map to Polygon bounds
function fitPolygon(){
bounds = Polygon.getBounds();
map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
}
//check is the marker is a polygon boundary marker
function checkPolygonMarkers(marker) {
var flag = false;
for (var m = 0; m < PolygonMarkers.length; m++) {
if (marker == PolygonMarkers[m])
{ flag = true; break; }
}
return flag;
}
//////////////////[ Key down event handler ]/////////////////////
//Event handler class to attach events
var EventUtil = {
addHandler: function(element, type, handler){
if (element.addEventListener){
element.addEventListener(type, handler, false);
} else if (element.attachEvent){
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
}
};
// Attach Key down/up events to document
EventUtil.addHandler(document, "keydown", function(event){keyDownHandler(event)});
EventUtil.addHandler(document, "keyup", function(event){keyUpHandler(event)});
//Checks for shift and Ctrl key press
function keyDownHandler(e)
{
if (!e) var e = window.event;
var target = (!e.target) ? e.srcElement : e.target;
if (e.keyCode == 16 && !global.shiftKey) { //Shift Key
global.shiftKey = true;
}
if (e.keyCode == 17 && !global.ctrlKey) { //Ctrl Key
global.ctrlKey = true;
}
}
//Checks for shift and Ctrl key release
function keyUpHandler(e){
if (!e) var e = window.event;
if (e.keyCode == 16 && global.shiftKey) { //Shift Key
global.shiftKey = false;
}
if (e.keyCode == 17 && global.ctrlKey) { //Ctrl Key
global.ctrlKey = false;
}
}
</script>
To initialize the map you can call the functions on page load event and include a div tag inside your body to hold the Map.
<body onload="initialize()" onunload="GUnload()"><div id="map_canvas" style="width:100%; height:450px"></div>
</body>
Feel free to modify and use this code on your website. I have used API v2 for my code but you can easily modify this code for API v3. Happy Mapping!
Excellent, thanks a lot for sharing this, now, if i wanted to save markers position in a db, what would i have to do?
ReplyDeleteYou have the marker array (PolygonMarkers)... just use that to populate a list of lat/longs and store it in db.
ReplyDeleteYou can populate a hidden field with lat/longs on your page and then submit it to next page for processing.
can you elaborate on how you extract each polygon marker value so that I can actually send them to a db, and then how you get a stored points in a db row to overlay/populate on a map. I dont even seem to be able to bring up an alert box to show me what my value is each time I click a point.
DeleteI have tried alert(JSON.stringify(PolygonMarkers)) and alert(PolygonMarkers[1]) and just cant get anything to show.
Hi Abhinay
DeleteHow can I store the marker array into the database?
How about an API v3 version?
ReplyDeleteHi Abhinav,
ReplyDeletecan you please suggest how can i initialize
var PolygonMarkers = []; and
var PolygonPoints = [];
i mean can you please put a dummy data into these 2 variables
Thanks in advance
ahh there is nothing to do with these 2 variables thanks a lot i got my desired solution
DeleteOooh yess!! After visited lots of page,come to actual mark point...
ReplyDeleteThanks..Its nice..
Hi I don't know if I made a simple mistake but the map seems to load then crash. Here is a fiddle of it
ReplyDeletehttp://jsfiddle.net/NathanTheGr8/uh1o4hf9/
Any help would be appreciated, thanks!
Hi Nathan,
DeleteTry removing 'YOUR_API_KEY' from script tag.
Thanks
can any one tell that how this PolygonMarkers can store in the database
ReplyDeletePython is a general-purpose interpreted, interactive, object-oriented and high-level programming language. Currently Python is the most popular Language in IT.
ReplyDeletepython training in bangalore | python online training
ReplyDeleteaws training in Bangalore | aws online training
ReplyDeleteartificial intelligence training in bangalore | artificial intelligence online training
machine learning training in bangalore | machine learning online training
data science training in bangalore | data science online training
online learning management system software
ReplyDeletegoogle meet alternative
online student management system
school software
school management erp