This question already has answers here:
How to get point coordinates of a modified drawingManager shape? GoogleMaps API v3
(2 answers)
Closed 9 years ago.
I have an example how to write polygon on google map:
http://jsbin.com/quzed/1/edit
So here is the code:
var drawingManager;
var selectedShape;
var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
var selectedColor;
var colorButtons = {};
function clearSelection() {
if (selectedShape) {
selectedShape.setEditable(false);
selectedShape = null;
}
}
function setSelection(shape) {
clearSelection();
selectedShape = shape;
shape.setEditable(true);
selectColor(shape.get('fillColor') || shape.get('strokeColor'));
}
function deleteSelectedShape() {
if (selectedShape) {
selectedShape.setMap(null);
}
}
function selectColor(color) {
selectedColor = color;
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
}
// Retrieves the current options from the drawing manager and replaces the
// stroke or fill color as appropriate.
var polylineOptions = drawingManager.get('polylineOptions');
polylineOptions.strokeColor = color;
drawingManager.set('polylineOptions', polylineOptions);
var rectangleOptions = drawingManager.get('rectangleOptions');
rectangleOptions.fillColor = color;
drawingManager.set('rectangleOptions', rectangleOptions);
var circleOptions = drawingManager.get('circleOptions');
circleOptions.fillColor = color;
drawingManager.set('circleOptions', circleOptions);
var polygonOptions = drawingManager.get('polygonOptions');
polygonOptions.fillColor = color;
drawingManager.set('polygonOptions', polygonOptions);
}
function setSelectedShapeColor(color) {
if (selectedShape) {
if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
selectedShape.set('strokeColor', color);
} else {
selectedShape.set('fillColor', color);
}
}
}
function makeColorButton(color) {
var button = document.createElement('span');
button.className = 'color-button';
button.style.backgroundColor = color;
google.maps.event.addDomListener(button, 'click', function() {
selectColor(color);
setSelectedShapeColor(color);
});
return button;
}
function buildColorPalette() {
var colorPalette = document.getElementById('color-palette');
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
var colorButton = makeColorButton(currColor);
colorPalette.appendChild(colorButton);
colorButtons[currColor] = colorButton;
}
selectColor(colors[0]);
}
function initialize() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(22.344, 114.048),
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
zoomControl: true
});
var polyOptions = {
strokeWeight: 0,
fillOpacity: 0.45,
editable: true
};
// Creates a drawing manager attached to the map that allows the user to draw
// markers, lines, and shapes.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
markerOptions: {
draggable: true
},
polylineOptions: {
editable: true
},
rectangleOptions: polyOptions,
circleOptions: polyOptions,
polygonOptions: polyOptions,
map: map
});
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type != google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function() {
setSelection(newShape);
});
setSelection(newShape);
}
});
// Clear the current selection when the drawing mode is changed, or when the
// map is clicked.
google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
google.maps.event.addListener(map, 'click', clearSelection);
google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);
buildColorPalette();
}
google.maps.event.addDomListener(window, 'load', initialize);
How i can see what are coordinates from drawen polygon, and how to save it (etc. mysql) also how to write polygon if you know coordinates ?
Can sombody help me? I lose in this code? Where is coordinates from user action (user drawing polygon)?
ETC. if I have 3 coordinates (44.5, 55.6) (45.7, 56.87) (46.7, 46.8) how I can draw it here?
And if I draw some polygon on example, how I can see coordinates for polygon?
Look at the example on google's site.
Given you already have that polygon, you can get it's path coordinates with the getPath method.
console.log(bermudaTriangle.getPath() );
There's also a setPath method which would accept an array of coordinates (or an MVCArray for that matter).
Polygons can also have interior rings (as in a donut), but you should get accustomed to simple convex polygons before trying that.
Regarding the question as to "how to save a drawn polygon", Google Maps API provides static functions to encode polygon and polyline paths so you can persist the objects as text.
There are other libraries such as Wicket that can take a Google Maps Object and encode it with a standard WKT format, that is natively understood by geometrical enabled databases.
Related
I am encountering an issue when drawing polygons, point, and line features on a map using the Leaflet.js library.
The polygon is correctly displayed on the map, but the moment I try to draw a point ** or **line, they **disappear **immediately after releasing the mouse click. I need assistance to correct this issue and make the drawing of points and lines on the map functional.
var map = L.map("leaflet-map", {
center: [37.7749, -122.4194],
zoom: 8,
});
let osm = L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}", {
foo: "bar",
attribution: "© OpenStreetMap contributors",
});
osm.addTo(map);
var CyclOSM = L.tileLayer(
"https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png",
{
attribution: "CyclOSM | Map data: © OpenStreetMap contributors",
}
);
CyclOSM.addTo(map);
var Esri_WorldImagery = L.tileLayer(
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
{
attribution:
"Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community",
}
).addTo(map);
let baseLayers = {
"Esri World Imagery": Esri_WorldImagery,
"Open Street Map": osm,
"Cycl OSM": CyclOSM,
};
//Creates three feature groups for points, polygons, and lines on the map
var pointLayer = L.featureGroup().addTo(map);
var polygonsLayer = L.featureGroup().addTo(map);
var lineLayer = L.featureGroup().addTo(map);
var polygon;
var point;
var line;
var allLayers = L.featureGroup([pointLayer, polygonsLayer, lineLayer]).addTo(
map
);
//Add new shapes drawn on the map to the appropriate feature group
map.on("draw:created", function (e) {
var type = e.layerType,
layer = e.layer;
if (type === "point") {
point = layer;
point.addTo(pointLayer);
point.addTo(map);
} else if (type === "polygon") {
polygon = layer;
polygon.addTo(polygonsLayer);
polygonsLayer.addTo(map);
} else if (type === "line") {
line = layer;
line.addTo(lineLayer);
lineLayer.addTo(map);
}
});
var drawControl = new L.Control.Draw({
draw: {
marker: true,
polyline: true,
polygon: true,
rectangle: true,
circle: true,
},
}).addTo(map);
You define 5 types of shapes:
marker, polyline, polygon, rectangle, and circle
but in the feature group, you only catch polyline
To catch makers, you need to change this block:
if (type === "point") {
point = layer;
point.addTo(pointLayer);
point.addTo(map);
to:
if (type === "marker") {
point = layer;
point.addTo(pointLayer);
pointLayer.addTo(map); //add the layer to the map
same for polyline, rectangle and circle.
You can have a look at the Leaflet Draw documentation, you can catch all shapes by not checking for type and directly adding the e.layer from the draw event to the map.
This question already has answers here:
Easiest way to calculate area of drawn polygon with google map
(1 answer)
Calculating area of a polygon drawn on google map
(2 answers)
Closed last month.
I don't have much experience in JavaScript. I am trying to get Area of polygon may be i am doing something wrong. I am using Google API. Every thing working good but unable to get draw polygon area. Below I have also uploaded one image on which I have draw polygon. Can anyone tell me how to find it's area.
var map;
var infoWindow;
var listOfPolygons = [];
var pdata = [
[43.7711057, -79.3696734, "Amritsar"],
[43.7442141, -79.407609, "oyeji"],
[43.7452141, -79.407609, "oyeji"],
];
function initMap() {
var locations = pdata;
var markers = [];
map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 43.717899, lng: -79.6582408 },
zoom: 5,
streetViewControl: false,
mapTypeControl: false
});
//Drawing tool
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.LEFT_TOP,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
],
}
})
drawingManager.setMap(map);
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < locations.length; i++) {
markers.push(
new google.maps.Marker({
position: {
lat: locations[i][0],
lng: locations[i][1]
},
title:"Amritsar"
})
);
bounds.extend(markers[markers.length - 1].getPosition());
}
map.fitBounds(bounds);
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
var poly = event.overlay.getPath();
//console.log(poly);
if (event.type == 'polygon') {
// hide polygon from DrawingManager
event.overlay.setMap(null);
//console.log(event.overlay.getPath().getArray());
listOfPolygons.push(new google.maps.Polygon({
paths: event.overlay.getPath().getArray(),
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35
}));
//console.log(markers.length);
for (var i = 0; i < markers.length; i++) {
if (google.maps.geometry.poly.containsLocation(markers[i].getPosition(), listOfPolygons[listOfPolygons.length - 1])) {
// show current marker
markers[i].setMap(map);
console.log(markers[i].getPosition());
}
}
listOfPolygons[listOfPolygons.length - 1].setMap(map);
listOfPolygons[listOfPolygons.length - 1].addListener('click', showArrays);
}
});
infoWindow = new google.maps.InfoWindow({
content : "Amritsar"
});
/** #this {google.maps.Polygon} */
function showArrays(event) {
// Since this polygon has only one path, we can call getPath() to return the
// MVCArray of LatLngs.
var vertices = this.getPath();
var contentString = '<b>polygon</b><br>' +
'Clicked location: <br>' + event.latLng.lat() + ',' + event.latLng.lng() +
'<br>';
// Iterate over the vertices.
for (var i = 0; i < vertices.getLength(); i++) {
var xy = vertices.getAt(i);
contentString += '<br>' + 'Coordinate ' + i + ':<br>' + xy.lat() + ',' +
xy.lng();
}
// Replace the info window's content and position.
//console.log(contentString);
infoWindow.setContent(contentString);
infoWindow.setPosition(event.latLng);
infoWindow.open(map);
}
}
My map locator works but I am not sure how to reset the marker so that when the user geolocates it resets the position. Currently, my code looks like this:
//map locator
map.locate({setView: true, maxZoom: 16});
function onLocationFound(e) {
var radius = e.accuracy;
L.marker(e.latlng).addTo(map)
.bindPopup("Vous êtes ici").openPopup();
L.circle(e.latlng, radius).addTo(map);
}
map.on('locationfound', onLocationFound);
function onLocationError(e) {
alert(e.message);
}
map.on('locationerror', onLocationError);
// end of geolocator with marker
Overwrite the latlng and radius:
var marker = null;
var circle = null;
//map locator
map.locate({setView: true, maxZoom: 16});
function onLocationFound(e) {
var radius = e.accuracy;
if(!marker){
marker = L.marker(e.latlng).addTo(map);
circle = L.circle(e.latlng,radius).addTo(map);
}else{
marker.setLatLng(e.latlng);
circle.setLatLng(e.latlng);
circle.setRadius(radius);
}
marker.bindPopup("Vous êtes ici").openPopup();
}
In my rails application I have implemented a google maps using the polygon drawing tool. I have been able to add coordinates and save these to my database successfully.
The problem i'm having is when a user wants to edit and save any changes made to the polygon shape. How do i implement this function? My best guess is to use a conditional to see if the database has any saved coordinates, if so, load them in a listener?
HTML
<div style='width: 100%;'>
<%= hidden_field_tag(:map_coords, value = nil, html_options = {id: 'propertyCoordinates'}) %>
Javascript
function initMap() {
var map = new google.maps.Map(document.getElementById("map"), {
center: { lat: -40.6892, lng: 74.0445 },
zoom: 8,
mapTypeId: google.maps.MapTypeId.HYBRID,
});
var polyOptions = {
strokeWeight: 0,
fillOpacity: 0.45,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
};
// loads databased saved coordinates
var propertyCoords = [<%= #property.coordinates %>];
var points = [];
for (var i = 0; i < propertyCoords.length; i++) {
points.push({
lat: propertyCoords[i][0],
lng: propertyCoords[i][1]
});
}
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: ["polygon"]
},
polylineOptions: {
editable: true,
draggable: true
},
rectangleOptions: polyOptions,
circleOptions: polyOptions,
polygonOptions: polyOptions,
map: map
});
if (typeof points !== 'undefined') {
// My guess is to use a conditional statement to check if the map has any coordinates saved?
} else {
google.maps.event.addListener(drawingManager, 'overlaycomplete', function (e) {
if (e.type !== google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function (e) {
if (e.vertex !== undefined) {
if (newShape.type === google.maps.drawing.OverlayType.POLYGON) {
var path = newShape.getPaths().getAt(e.path);
path.removeAt(e.vertex);
if (path.length < 3) {
newShape.setMap(null);
}
}
}
setSelection(newShape);
});
}
var coords = e.overlay.getPath().getArray();
document.getElementById("propertyCoordinates").value = coords;
});
}
} // END function initMap()
If I understand correctly, what you're looking for is the polygon editing functionality. My stackblitz example goes something like this:
Draw a polygon if you already have user-saved coordinates. Then fit the map bounds to the poly's bounds. For this you'll probably need a getBounds polyfill.
Make the polygon editable so you can listen to its points' changes. Check the function enableCoordinatesChangedEvent.
Listen to the changes & extract the new polygon points. Look for function extractPolygonPoints.
Then proceed with your business logic.
FYI you'll need to put your own API key at the bottom of the stackblitz index.html. Look for YOUR_KEY.
I have recently integrated drawing functions in a website. But I want to be able to clear the map without having to recharge the whole page.
I followed this great example about Custom Controls in order to add a well-integrated button that react on click.
Also, I read the DrawingManager documentation, there is several options you can play with, but nothing about clearing a map.
Based on the Custom Controls example, I would like to do something like that:
controlUI.addEventListener('click', function() {
clearMap();
});
But I don't know how to get an array of drawn objects in order to erase them.
If you can't find an array of drawn objects, you can at least create one.
At the bottom of the link that you provided, there is something helpful about Drawing Events.
So if you want to clear the map with a custom control, the idea is to hold a list of these objects since they are created. For example, with circles and rectangles:
First hold a global array of desired objects (here, circles and rectangles):
var circles = [];
var rectangles = [];
Then initialize your map (it needs to be done BEFORE adding the drawing API):
function initMap(){
// Your initializations
initDrawings();
}
Then, init your DrawingManager as desire and add event listeners. Don't forget to add the control button:
function initDrawings(){
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: null,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.BOTTOM_CENTER,
drawingModes: ['circle', 'rectangle']
},
markerOptions: {icon: '/path/to/icon.png'},
circleOptions: {
fillColor: '#ffff00',
fillOpacity: 0.25,
strokeWeight: 3,
zIndex: 1
}
});
google.maps.event.addListener(drawingManager, 'circlecomplete', updateDrawings);
google.maps.event.addListener(drawingManager, 'rectanglecomplete', updateDrawings);
drawingManager.setMap(map);
var eraseControlDiv = document.createElement('div');
var eraseControl = new EraseButton(eraseControlDiv,map);
eraseControlDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_CENTER].push(eraseControlDiv);
}
function EraseButton(controlDiv, map) {
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = '#fff';
controlUI.style.border = '2px solid #fff';
controlUI.style.borderRadius = '3px';
controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
controlUI.style.cursor = 'pointer';
controlUI.style.marginBottom = '20px';
controlUI.style.textAlign = 'center';
controlUI.title = 'Click to clear map';
controlDiv.appendChild(controlUI);
var controlText = document.createElement('div');
controlText.style.color = 'rgb(25,25,25)';
controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.lineHeight = '38px';
controlText.style.paddingLeft = '5px';
controlText.style.paddingRight = '5px';
controlText.innerHTML = 'Empty Map';
controlUI.appendChild(controlText);
controlUI.addEventListener('click', emptyMap);
}
Here is the function that check the shape of the object that triggered a shapecomplete event. It just adds an element in the corresponding array.
function updateDrawings(shape){
if(shape == null) return;
if(shape instanceof google.maps.Circle){
circles.push(shape);
}
else if (shape instanceof google.maps.Rectangle) {
rectangles.push(shape);
}
}
And here, we set these elements out of the map, and we clear each list.
function emptyMap(){
circles.forEach(function(e){
e.setMap(null);
});
rectangles.forEach(function(e){
e.setMap(null);
});
circles = [];
rectangles = [];
}