After searching the whole day, I didn't find the answer.
So the problem is:
I have a Google Map on which the user can draw. After this, the user can save it on the server. It works fine. Here is the drawing code:
var drawingManager;
var selectedShape;
var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
var selectedColor;
var colorButtons = {};
var all_overlays = [];
var coordinates;
var polygon;
var globalGoogleSelectedColor;
var globalGooglePinWidth;
var map;
coordObj = new Object();
function clearSelection()
{
if (selectedShape)
{
deleteAllLastShape();
selectedShape.setEditable(false);
selectedShape = null;
deleteObjectContent(coordObj);
}
}
function setSelection(shape)
{
clearSelection();
selectedShape = shape;
shape.setEditable(true);
selectColor(shape.get('fillColor') || shape.get('strokeColor'));
}
function deleteAllShape()
{
console.log("deleteAllShape");
deleteObjectContent(coordObj);
for (var i=0; i < all_overlays.length; i++)
{
all_overlays[i].overlay.setMap(null);
}
all_overlays = [];
}
function deleteAllLastShape()
{
var myLenth = all_overlays.length;
if(myLenth > 1)
{
all_overlays[0].overlay.setMap(null);
all_overlays = _.rest(all_overlays);
}
}
function deleteSelectedShape()
{
if (selectedShape)
{
selectedShape.setMap(null);
deleteObjectContent(coordObj);
}
}
function selectColor(color)
{
selectedColor = color;
globalGoogleSelectedColor = selectedColor;
globalGooglePinWidth = 2; //only for Database
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 initializeAreas()
{
map = new google.maps.Map(document.getElementById('mapBaugebieteDiv'),
{
zoom: 15,
center: new google.maps.LatLng(48.758961357888516,8.240861892700195),
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DEFAULT,
mapTypeIds: [
google.maps.MapTypeId.ROADMAP,
google.maps.MapTypeId.TERRAIN,
google.maps.MapTypeId.SATELLITE,
google.maps.MapTypeId.HYBRID
]},
disableDefaultUI: false,
zoomControl: true,
scaleControl: true,
mapTypeControl: true,
streetViewControl: true,
rotateControl: 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,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
// google.maps.drawing.OverlayType.MARKER,
// google.maps.drawing.OverlayType.CIRCLE,
google.maps.drawing.OverlayType.POLYLINE,
// google.maps.drawing.OverlayType.RECTANGLE,
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)
{
// Push the overlay onto an array (all_overlays):
all_overlays.push(e);
deleteAllLastShape();
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);
google.maps.event.addDomListener(document.getElementById('delete-all-button'), 'click', deleteAllShape);
///////////////////////////////////////
// Polylgon
///////////////////////////////////////
google.maps.event.addListener(drawingManager, 'polygoncomplete', function (polygon)
{
var shapeType = 'polygon';
google.maps.event.addListener(polygon.getPath(), 'insert_at', function()
{
// New point
coordinates = (polygon.getPath().getArray());
showObjectContent(coordinates);
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
google.maps.event.addListener(polygon.getPath(), 'remove_at', function()
{
// Point was removed
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
google.maps.event.addListener(polygon.getPath(), 'set_at', function()
{
// Point was moved
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
google.maps.event.addListener(polygon, 'dragend', function()
{
// Polygon was dragged
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
///////////////////////////////////////
// Polyline
///////////////////////////////////////
google.maps.event.addListener(drawingManager, 'polylinecomplete', function (polygon)
{
var shapeType = 'polyline';
google.maps.event.addListener(polygon.getPath(), 'insert_at', function()
{
// New point
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
google.maps.event.addListener(polygon.getPath(), 'remove_at', function()
{
// Point was removed
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
google.maps.event.addListener(polygon.getPath(), 'set_at', function()
{
// Point was moved
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
google.maps.event.addListener(polygon, 'dragend', function()
{
// Polygon was dragged
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
coordinates = (polygon.getPath().getArray());
coordObj = getCoordinatesOfPolygon(polygon,shapeType);
});
buildColorPalette();
}
google.maps.event.addDomListener(window, 'load', initializeAreas);
But the big problem is, after reloading the lat/lng from the server and drawing it on the map, the event listener does not know about the new polygon:
function fillBuildingForm(getData)
{
var coord = getData['buildings']; // coordinates from the server
if(typeof coord[0] !== 'undefined')
{
var shapeType = coord[0]['shapeType'];
var color = coord[0]['color'];
var strokeOpacity = coord[0]['opacity'];
var strokeWeight = coord[0]['linewidth'];
var numberOfCoord = getObjectSize(coord);
var flightPlanCoordinates = new Array();
for (var i = 0; i < numberOfCoord; i++)
{
thisCoord = new Object();
thisCoord['lat']=parseFloat(coord[i]['lat']);
thisCoord['lng']=parseFloat(coord[i]['lng']);
flightPlanCoordinates.push(thisCoord);
};
var bermudaTriangle = new google.maps.Polygon(
{
paths: flightPlanCoordinates,
strokeColor: color,
strokeOpacity: strokeOpacity,
strokeWeight: strokeWeight,
fillColor: color,
fillOpacity: 0.35,
// bounds: flightPlanCoordinates,
editable: true,
draggable: true
});
bermudaTriangle.setMap(map); //now its drawing at the map
}
}
You can see, until now, it works perfectly:
But the user can change the polygon and want to save the new changed polygon on the server. The listener:
google.maps.event.addListener(drawingManager, 'polygoncomplete', function (polygon)
Does not recognize that the polygon has been drawn. And therefore the listener doesn't recognize when the user changes the polygon.
So the coordinates are not present in all_overlays[i].
The listener only recognizes when a polygon is drawn manually, but not in the way like the above, when it is drawn automatically.
The question: How can I send the automatically drawn polygon coordinates to the "map" object? Alternatively, how can I fire an event to "polygoncomplete", so it will recognize the new polygon?
The other idea I had: Trigger a mouse click event at the map with the coordinates, so the listener must recognize that the map has changed. But unfortunately this didn't work.
Has anybody any idea how to solve this issue?
There are not many possibilities as an event "polygon_load _complete" is not available. One suggestion is to exploit the fact that to operate on a polygon you must click it.
If you need to manage the situation when a polygon is loaded from server and the user change the shape/coordinates. you can add listener on click to every polygon during the loading phase ..
for each polygon in loading phase..
var aPoly = new google.maps.Polygon({
paths:myPaths,
.......
});
google.maps.event.addListener(aPoly, 'click', function (event) {
console.log('This polygon contain : ' + this.paths + ' coords point ');
});
In this way you can intecept the click on polygon for manage your need
your idea was a good intention, but not the end of the solution. But thank you for your hint. Because of your answer I was able finding a way.
Generally we should think, the object bermudaTriangle should have the property "paths". But it doesn't work like this way.
For getting the coordinates of the loaded Poly (loaded from server) there is a google-map function like "getPath()" or"getPaths()". It seems, that both methods are working.
Please note, I've changed the name from 'bermudaTriangle' to 'globalLoadedPoly'.
So the solution is in combination with the above code now additional:
Creating a global var:
var globalLoadedPoly;
(global is not necessary, but I did it this way for further actions)
Getting the path by function for the listeners:
var thisPolyPath = globalLoadedPoly.getPath();
Listening to events, when the loaded poly has changed:
google.maps.event.addListener(thisPolyPath, 'set_at', thisPolyHasChanged);
google.maps.event.addListener(thisPolyPath, 'insert_at', thisPolyHasChanged);
4.In the function, thisPolyHasChanged(), setting the loaded poly as the actual selection, by using the function setSelection(shape). And getting the coordinates by calling the function getCoordinatesOfLoadedPolygon
function thisPolyHasChanged()
{
// Setting the loaded poly as the new selection
// Yes, it's global, so therefore not necessary to be sent
// but like this way, it's more readable
setSelection(globalLoadedPoly);
// If you want to get the coordinates for saving
// Calling the function getCoordinatesOfLoadedPolygon
// For being more readable I send the global Object - yes, it's not necessary
coordObj = getCoordinatesOfLoadedPolygon(globalLoadedPoly,'polygon');
// do something with coordObj
// ...
}
function setSelection(shape)
{
// clearSelection is in the code I postet as the question
clearSelection();
selectedShape = shape; // setting the loaded poly as the actual poly
shape.setEditable(true); // making the loaded poly editable
selectColor(shape.get('fillColor') || shape.get('strokeColor')); //setting the color
}
function getCoordinatesOfLoadedPolygon(getPolygon,shapeType)
{
// getLength is also a google-maps function / method
var objSize = getPolygon.getPath().getLength();
for (var i = 0; i < objSize; i++)
{
// getArray is a google-maps function / method too
var thisLat = getPolygon.getPath().getArray()[i].lat();
var thisLng = getPolygon.getPath().getArray()[i].lng();
coordObj[i]=new Object();
coordObj[i]['lat']=thisLat;
coordObj[i]['lng']=thisLng;
coordObj[i]['shapeType']=shapeType;
};
return coordObj;
}
At last, if you iterate the object "coordObj" and make a console.log in firebug, it looks like this way:
0 Object { lat=51.25572693191116, lng=9.136230200529099, shapeType="polygon"}
1 Object { lat=51.80250070611026, lng=13.069335669279099, shapeType="polygon"}
2 Object { lat=49.958995050387585, lng=10.476562231779099, shapeType="polygon"}
Conclusion:
If you want to get the coordinates or other properties of a google-maps object, use the proprietary google-maps functions / methods:
// For getting the coordinates you are generally working with:
yourMapObject.getPath();
//or
yourMapObject.getPaths();
// Getting especially the latitude:
var latitude = yourMapObject.getPath().getArray()[i].lat();
// Getting especially the longitude:
var longitude = yourMapObject.getPath().getArray()[i].lng();
// Getting the number of coordinates
yourMapObject.getPath().getLength();
Don't forget to iterate over the whole object, to get all coordinates.
The solution-code could be really optimized. For being more readable, I wrote it in small steps.
I hope, I'm able helping anybody with this solution.
Related
I am trying to get the lat lng of the polygon while drawing the polygon on google map. Does anyone know what event is triggered when we plot the points of polygon.
Basically what I am trying to do is undo/redo function for the polygon. So when a user plots 2 points one then clicks undo then it should be able to delete 1 point on one click.
As the map click event is disabled while drawing a polygon how to get the lat lng points? Is it possible what I am trying to do? Can anyone please help me with this? Any links or examples that I could refer to?
Below is my code to draw polygon:
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: false,
polygonOptions: {
strokeWeight: 2,
fillOpacity: 0.2,
editable: true,
fillColor: '#FFF000',
strokeColor: '#FFF000',
geodesic: true,
suppressUndo: true
},
polylineOptions: {
editable: false,
suppressUndo: true
}
});
drawingManager.setMap(map);
Try this
var myPoly;
google.maps.event.addListener(drawingManager, 'polygoncomplete', function(polygon) {
myPoly = polygon;
get_coordinates(polygon);//call to get coordinates
//editing polygon function
google.maps.event.addListener(polygon.getPath(), 'set_at', function() {
get_coordinates(polygon);//call to get coordinates
});
var newShape = polygon.overlay;
//newShape.type = polygon.type;
google.maps.event.addListener(newShape, 'click', function() {
setSelection(newShape);
});
setSelection(newShape);
});
and the get coordinate function
//function to get coordinates of polygon
function get_coordinates(polygon){
var full_path = [];//initialize array for set coordinates.
polygon.getPath().forEach(function(elem, index){
full_path.push(elem.toUrlValue());
});
return full_path;
}
ok. I can give you all the functions you need. You can integrate last code with the following. And you cannot delete any point but replace it.
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);
I'm using mosne map (www.mosne.it/playground/mosne_map)
What I'm trying to do is, whenever user change zoom level < 10 the image will be changed. Here's what I got now:
currently the marker doesn't change whenever user changes zoom level
$.fn.mosne_map = function (options) {
var baseconf = {
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var s_infobox = {
content: "",
disableAutoPan: false,
maxWidth: 0,
pixelOffset: new google.maps.Size(-110, 5),
zIndex: null,
boxStyle: {
background: "url('images/infobox_top.png') top center no-repeat",
opacity: 1,
color: '#fff',
padding: '0',
width: "300px"
},
closeBoxMargin: "16px 4px",
closeBoxURL: "images/infobox_close_hd2.png",
infoBoxClearance: new google.maps.Size(1, 1),
isHidden: false,
pane: "floatPane",
enableEventPropagation: false
};
defaults = {
elements: '#list .maplocation', //links selector
map_opt: baseconf, // custom map options object
clat: -9.460181, // set the lat default map center
clng: 100.988281, // set the lng default map center
mapstyle_name: '', // custom map style label and id
mapstyle: '', // mapstyle object
cluster_styles: {}, // custom cluster icons object
marker_icon: {}, // custom marker icon url,width,height
infowindows: true, // shows infoWindows grabing html from the .infobox element
infobox: false, // enable custom infoWindows using infobox class
infobox_s: s_infobox, // default color scheme for custom infobox container
trigger: 'map_open', // you can set a event trigger for each link/marker
clickedzoom: 15, // set the zoom level when you click the single marker
timeout: 100, // delay between click and zoom on the single marker
mode: 'latlng', // switch mode
wait: 500, // timeout between geocode requests
maxtry: 10, // limit of time to bypass query overlimit
cat_style: {}, // costum icons and click zoom level
fitbounds: false, // on|off fit bounds
defzoom: 3, // default zoom level if fitbounds is off
showzoom: false, // bind current map zoom level event
before: function () {}, // before create map callback
after: function () {}, // after create map callback
afterUpdate: function () {} // after update map callback
};
var settings = $.extend({}, defaults, options);
this.each(function () {
var map_el = $(this);
var the_map_el = $(this).get(0);
//on before
settings.before.apply(map_el);
//init map
var center = new google.maps.LatLng(settings.clat, settings.clng);
var map = new google.maps.Map(the_map_el, settings.map_opt);
var bounds = new google.maps.LatLngBounds();
var markerCluster = new MarkerClusterer(map, null, settings.cluster_styles);
map.setCenter(center);
bounds.extend(center);
map.setZoom(settings.defzoom);
map.setCenter(center);
//apply map style
if (settings.mapstyle_name != '') {
var styledMapOptions = {
name: settings.mapstyle_name
};
var m_MapType = new google.maps.StyledMapType(settings.mapstyle, styledMapOptions);
map.mapTypes.set(settings.mapstyle_name, m_MapType);
map.setMapTypeId(settings.mapstyle_name);
}
// set markers icons
var markerIcon = new google.maps.MarkerImage("http://googlemaps.googlermania.com/img/google-marker-big.png");
// init infowindow
if (settings.infowindows) {
var infowindow = new google.maps.InfoWindow({
maxWidth: 200
});
}
// init infobox
if (settings.infobox) {
var boxText = document.createElement("div");
boxText.style.cssText = settings.infobox_s_txt
boxText.innerHTML = "hello world";
var m_box = new InfoBox(settings.infobox_s);
}
// function create marker
var _createMarker = function (el, latLng, markerIcon, m_name, cat) {
if (cat) {
var c_icon = settings.cat_style[cat]['icon'];
var c_icon_w = settings.cat_style[cat]['width'];
var c_icon_h = settings.cat_style[cat]['height'];
if (c_icon) { //var markerIcon = c_icon;
var markerIcon = new google.maps.MarkerImage(c_icon, null, null, null, new google.maps.Size(c_icon_w, c_icon_h));
}
}
var marker = new google.maps.Marker({
position: latLng,
icon: markerIcon,
flat: true,
title: m_name
});
//extend bounds
bounds.extend(latLng);
// bind click on map trigger event fill infowindow / infobox content on demand
if (settings.infowindows || settings.infobox) {
var content = el.find('.infobox').html();
}
google.maps.event.addListener(marker, 'click', function () {
if (settings.infowindows) {
infowindow.close();
infowindow.setContent(content);
infowindow.open(map, marker);
map.setCentexxxr(marker.getPosition());
}
if (settings.infobox) {
m_box.close();
$(boxText).hide();
m_box.setContent(content);
m_box.open(map, marker);
$(boxText).show("slow");
map.setCentesr(marker.getPosition());
}
el.trigger(settings.trigger);
$(el).parent().find('.active').removeClass('active');
$(el).addClass('active');
setTimeout(function () {
map.setZoom(settings.clickedzoom);
map.panTo(latLng);
marker.setAnimation(google.maps.Animation.DROP);
}, settings.timeout);
});
// trigger click on list
$(el).find('.maplink').unbind("click").bind("click", function (e) {
e.preventDefault();
google.maps.event.trigger(marker, "click");
return false;
});
markerCluster.addMarker(marker);
};
var _m_geocode = function (el, geocoder, address, name, cat, j) {
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latLng = results[0].geometry.location;
_createMarker(el, latLng, markerIcon, name, cat);
if (settings.fitbounds === true) {
map.fitBounds(bounds);
}
} else {
if (status === "OVER_QUERY_LIMIT") {
setTimeout(function () {
//console.log("trying again "+g_address);
j++;
if (j <= settings.maxtry) {
_m_geocode(el, geocoder, address, name, cat, j);
} else {
$(el).css({
opacity: .35
});
}
}, settings.wait);
} else if (status === "ZERO_RESULTS") {
$(el).css({
opacity: .35
});
}
}
});
}
//
$(map_el).bind('update', function () {
//reset cluster and bounds
markerCluster.clearMarkers();
bounds = null;
bounds = new google.maps.LatLngBounds();
// markers loop
var markers = [];
var w_delay = 0;
if (settings.mode === 'address') {
var geocoder = new google.maps.Geocoder();
}
var totel = $(settings.elements).length;
$(settings.elements).each(function (i) {
// create marker
var el = $(this);
//mode geocoding
if (settings.mode === 'address') {
var mkr = el.data();
var name = $(this).find(".name").text();
var address = $(this).find(".address").text();
setTimeout(function () {
_m_geocode(el, geocoder, address, name, mkr.cat, 0);
}, settings.wait * i);
} else {
// mode latlng
var mkr = el.data();
var latLng = new google.maps.LatLng(mkr.lat, mkr.lng);
_createMarker(el, latLng, markerIcon, mkr.name, mkr.cat);
}
//end of the elements loop
});
if (settings.fitbounds === true) {
// log(bounds);
map.fitBounds(bounds);
if (totel == 1) {
map.setZoom(settings.clickedzoom);
}
if (totel == 0) {
map.setZoom(settings.defzoom);
map.setCenter(center);
}
// map.setCenter(center);
} else {
//map.setZoom(settings.defzoom);
//map.setCenter(center);
};
//callbak afterUpdate
settings.afterUpdate.apply(map_el);
}).trigger('update');
$(map_el).bind('bounds', function () {
map.fitBounds(bounds);
});
// nice zoom status
if (settings.showzoom) {
google.maps.event.addListener(map, 'zoom_changed', function () {
$(map_el).trigger("showzoom", [map.getZoom()]);
});
};
//on after
settings.after.apply(map_el);
return true;
//change markerIcon
google.maps.event.addListener(map, 'zoom_changed', function() {
var zoom = map.getZoom();
if (zoom <= 10) {
var markerIcon = new google.maps.MarkerImage("http://i.stack.imgur.com/B2Vg5.png");
}
else {
var markerIcon = new google.maps.MarkerImage ("http://googlemaps.googlermania.com/img/google-marker-big.png")
}
});
});
};
A simple solution for a single icon(not a single marker, this method will change the icon of all markers, but there is also an option to define category-markers)
This is the code that currently defines the default-icon:
// set markers icons
var markerIcon = new google.maps.MarkerImage("http://googlemaps.googlermania.com/img/google-marker-big.png");
Replace it with this code:
// set markers icons
var markerIcon = new google.maps.MVCObject();
google.maps.event.addListener(map,'zoom_changed',function(){
markerIcon.set('icon',(this.getZoom()<10)
? 'http://www.google.com/mapfiles/marker.png'//url for zoom<10
: 'http://googlemaps.googlermania.com/img/google-marker-big.png'//url for zoom>=10
);
});
google.maps.event.trigger(map,'zoom_changed',{});
The url of markerIcon now will be updated when the zoom changes
To apply the changes to the markers replace this code:
var marker = new google.maps.Marker({
position: latLng,
icon: markerIcon,
flat: true,
title: m_name
});
with.....
var marker = new google.maps.Marker({
position: latLng,
icon: markerIcon.icon,
flat: true,
title: m_name
});
marker.bindTo('icon',markerIcon,'icon') ;
I currently have these codes to load GPX File into Google Maps
function loadGPXFileIntoGoogleMap(map, filename) {
$.ajax({url: filename,
dataType: 'xml',
success: function(data) {
var parser = new GPXParser(data, map);
parser.setTrackColour('#ff0000'); // Set the track line colour
parser.setTrackWidth(5); // Set the track line width
parser.setMinTrackPointDelta(0.001); // Set the minimum distance between track points
parser.centerAndZoom(data);
parser.addTrackpointsToMap(); // Add the trackpoints
parser.addWaypointsToMap(); // Add the waypoints
}
});
}
$(document).ready(function() {
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map'), mapOptions);
loadGPXFileIntoGoogleMap(map, '" . base_url('gps/ajax/request/trace') . "');
});
Everything is good but I want to replace it with arrow lines instead of straight line. Is it possible? If yes, please help me to do it.
In order to add arrows to the polylines created by the GPXParser, you need to modify that library to give access to the polylines, see the two lines and the function added to that library below. Then get the polylines and add the arrows to them as below.
working example (based off the example in the gpxviewer documentation referenced above)
Changes to the code from the example in the documentation:
function loadGPXFileIntoGoogleMap(map, filename) {
$.ajax({url: filename,
dataType: "xml",
success: function(data) {
var parser = new GPXParser(data, map);
parser.setTrackColour("#ff0000"); // Set the track line colour
parser.setTrackWidth(5); // Set the track line width
parser.setMinTrackPointDelta(0.001); // Set the minimum distance between track points
parser.centerAndZoom(data);
parser.addTrackpointsToMap(); // Add the trackpoints
// ******************** added *******************************
var polylines = parser.getPolylines();
// documentation on pre-defined symbols and repeated symbols:
// https://developers.google.com/maps/documentation/javascript/symbols
// Define a symbol using a predefined path (an arrow)
// supplied by the Google Maps JavaScript API.
var lineSymbol = {
path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
strokeColor: '#00FF00',
strokeOpacity: 1.0
};
for (var i=0; i<polylines.length; i++) {
polylines[i].setOptions({
icons: [{
icon: {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
strokeColor:'#0000ff',
fillColor:'#0000ff',
fillOpacity:1,
scale: 3
},
repeat:'100px'
}]
});
}
// *****************************end added**********************
parser.addWaypointsToMap(); // Add the waypoints
}
});
}
Changes to the loadgpx.js library:
function GPXParser(xmlDoc, map) {
this.xmlDoc = xmlDoc;
this.map = map;
this.trackcolour = "#ff00ff"; // red
this.trackwidth = 5;
this.mintrackpointdelta = 0.0001
this.polylines = []; // **added**
}
// return a reference to the array of polylines **added function**
GPXParser.prototype.getPolylines = function() {
return this.polylines;
}
GPXParser.prototype.addTrackSegmentToMap = function(trackSegment, colour,
width) {
var trackpoints = trackSegment.getElementsByTagName("trkpt");
if(trackpoints.length == 0) {
return;
}
var pointarray = [];
// process first point
var lastlon = parseFloat(trackpoints[0].getAttribute("lon"));
var lastlat = parseFloat(trackpoints[0].getAttribute("lat"));
var latlng = new google.maps.LatLng(lastlat,lastlon);
pointarray.push(latlng);
for(var i = 1; i < trackpoints.length; i++) {
var lon = parseFloat(trackpoints[i].getAttribute("lon"));
var lat = parseFloat(trackpoints[i].getAttribute("lat"));
// Verify that this is far enough away from the last point to be used.
var latdiff = lat - lastlat;
var londiff = lon - lastlon;
if(Math.sqrt(latdiff*latdiff + londiff*londiff)
> this.mintrackpointdelta) {
lastlon = lon;
lastlat = lat;
latlng = new google.maps.LatLng(lat,lon);
pointarray.push(latlng);
}
}
var polyline = new google.maps.Polyline({
path: pointarray,
strokeColor: colour,
strokeWeight: width,
map: this.map
});
this.polylines.push(polyline); // **added
}
I have an event listener for mousedown. The event fires the same result on left and right button press. How do I determine which mouse button has been pressed ?
google.maps.event.addListener(map, 'mousedown', function (e) {
console.log(e);
}
The event (e) returns Dm Class object and has only the properties:
Z, latLng, pixel.
It also returns prototype function stop().
After much of head banging, I think I have a workaround for this solution. Any better ideas and suggestions would be very much appreciated.
I was trying to mimic the Google Earth's creating path feature in Google Maps. Here is my experimental code:
function PolylineMarker(bounds, image, map) {
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
// We define a property to hold the image's
// div. We'll actually create this div
// upon receipt of the add() method so we'll
// leave it null for now.
this.div_ = null;
// Explicitly call setMap() on this overlay
this.setMap(map);
}
PolylineMarker.prototype = new google.maps.OverlayView();
PolylineMarker.prototype.onAdd = function() {
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement('div');
div.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
// Create an IMG element and attach it to the DIV.
// var img = document.createElement("img");
// img.src = this.image_;
// img.style.width = "100%";
// img.style.height = "100%";
// div.appendChild(img);
// Set the overlay's div_ property to this DIV
this.div_ = div;
// We add an overlay to a map via one of the map's panes.
// We'll add this overlay to the overlayImage pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
PolylineMarker.prototype.draw = function() {
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's DIV to fit the indicated dimensions.
var div = this.div_;
div.style.left = (sw.x - 3 ) + 'px';
div.style.top = (ne.y - 3 ) + 'px';
div.style.width = (ne.x - sw.x + 6) + 'px';
div.style.height = (sw.y - ne.y + 6) + 'px';
div.style.background = 'red';
div.style.margin = '0 auto';
}
PolylineMarker.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
// Note that the visibility property must be a string enclosed in quotes
PolylineMarker.prototype.hide = function() {
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
PolylineMarker.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = "visible";
}
}
PolylineMarker.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
PolylineMarker.prototype.toggleDOM = function() {
if (this.getMap()) {
this.setMap(null);
} else {
this.setMap(this.map_);
}
}
function initialize() {
var map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 15,
center: new google.maps.LatLng(27.703744, 85.333729),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var polyOptions = {
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 1,
map: map,
clickable: false,
icons: [{
'icon': {
path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
strokeOpacity: 0.8,
strokeWeight: 2,
strokeColor: '#000'
},
'offset': '100%',
'repeat': '100px'
}]
};
var polyline = null;
var mouseMoveHandler = null;
var button = '';
var isMouseReleased = false;
google.maps.event.addDomListener(document.getElementById("map-canvas"), 'mousedown', function(e) {
button = e.button;
isMouseReleased = false;
return false;
});
var mouseDownHandler = google.maps.event.addListener(map, 'mousedown', function (e) {
map.setOptions({
'draggable': false
});
if (!polyline) {
polyline = new google.maps.Polyline(polyOptions);
}
isMouseReleased = false;
setTimeout(function() {
if (! isMouseReleased) {
mouseMoveHandler = google.maps.event.addListener(map, 'mousemove', function (e) {
if (button == 0) {
var path = polyline.getPath();
/**
* Add new overlay
*/
var image = '';
var bounds = new google.maps.LatLngBounds(e.latLng, e.latLng);
var overlay = new PolylineMarker(bounds, image, map);
path.push(e.latLng);
}
e.stop();
});
}
}, 100);
e.stop();
});
google.maps.event.addListener(map, 'mouseup', function (e) {
isMouseReleased = true;
google.maps.event.clearListeners(map, 'mousemove');
google.maps.event.removeListener(mouseMoveHandler);
if (button == 0) {
polyline.getPath().push(e.latLng);
/**
* Add new overlay
*/
var image = '';
var bounds = new google.maps.LatLngBounds(e.latLng, e.latLng);
var overlay = new PolylineMarker(bounds, image, map);
map.setOptions({
'draggable': true
});
}
e.stop();
});
} // end of initialize function
google.maps.event.addDomListener(window, 'load', initialize);
Here is my demo : http://jsfiddle.net/himal/C6jMU/2/
which is a property of the event object, which most people label as e
in their event handlers. It contains the key code of the key which was
pressed to trigger the event.
As per your code add which to it.
google.maps.event.addListener(map, 'mousedown', function (e) {
console.log(e.which);
}
Check console:
left Click: 1
middle button click: 2
right click: 3
After checking Google docs, instead of getting the mouse keyCodes you can directly use their mouse event.
Go right to its object. BUT google for a reason I dont know change the object var name (xa,ta,ha...), so get it by its position is much more safe and will prevent you from having to change it from time to time. This works for me:
google.maps.event.addListener(map, 'mousedown', function (e) {
console.log('Button: ' + Object.value(e)[1].which);
}
Console:
Button: 1
Since google maps api v3 doesn't support start or end editing of a polygon or polyline I am trying to construct one of my own.
I am drawing markers for each point, then to finish editing I set all marker to hide when the first index point ("0") is clicked then set the polygon to clickable is true. But the user can still click the map and continue drawing the polygon. I want to disable that event listener but re-enable it on mouse over.. Can this be done? If I use Remove Listener can I reattached another listener to the polygon on mouseover so they can edit it?
MapShaper.Feature.prototype.poly = function(type) {
var color = MapShaper.getColor(false),
path = new google.maps.MVCArray,
poly,
self = this,
el = type + "_b";
if(type=="shape"){
poly = self.createShape( {strokeWeight: 3, fillColor: color}, path );
}else if(type=="line"){
poly = self.createLine( {strokeWeight: 3, strokeColor: color }, path );
}
poly.markers = new google.maps.MVCArray;
google.maps.event.addListener(poly, "mouseover", function(){
poly.markers.forEach(function(polyMarker, index){
polyMarker.setVisible(true);
});
});
MapShaper.Feature.prototype.createShape = function(opts, path) {
var poly;
poly = new google.maps.Polygon({
clickable:false,
strokeWeight: opts.strokeWeight,
fillColor: opts.fillColor
});
poly.setPaths(new google.maps.MVCArray([path]));
return poly;
}
MapShaper.Feature.prototype.createShape = function(opts, path) {
var poly;
poly = new google.maps.Polygon({
clickable:false,
strokeWeight: opts.strokeWeight,
fillColor: opts.fillColor
});
poly.setPaths(new google.maps.MVCArray([path]));
return poly;
}
google.maps.event.addListener(marker, 'click', function() {
if (!marker.index == 0) {
marker.setMap(null);
markers.removeAt(marker.index);
path.removeAt(marker.index);
MapShaper.reindex(markers);
if(markers.getLength() == 0){
MapShaper.removeFeature(poly.id);
}
} else {
markers.forEach(function(marker, index) {
marker.setVisible(false)
});
poly.setOptions({clickable: true});
}
});
You can do pretty much the same thing with a global variable, like so:
(and set disableListener = true; to disable it)
var disableListener = false;
google.maps.event.addListener(marker, 'click', function() {
if (disableListener)
return;
if (!marker.index == 0)
marker.setMap(null);
}