I am trying to create multiple rectangles with info windows on a Google Map. I have followed the pattern used for multiple markers found at Generating Google Maps markers From Database
I first used that example and used one of the lat and one of long to display icons on the map. That worked. Then I change the code to rectangles and added bounds. But no rectangles appear on the map. I tried to hard code one of the rectangles on the map and one rectangle appeared.
I also made sure that the description to be used in the infowindow did not have any links in. I found that to be a problem if I was passing a link in the data variable. But I could get the link to work if I add the variable with a link at the point of the creation of the infowindow content.
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var markers = [
<asp:Repeater ID="rptMarkers" runat="server">
<ItemTemplate>
{
"title": '<%# Eval("Quad_Name") %>',
"north": '<%# Eval("poly_north") %>',
"east": '<%# Eval("poly_east") %>',
"south": '<%# Eval("poly_south") %>',
"west": '<%# Eval("poly_west") %>',
"description": '<%# Eval("smqcomment") %>'
}
</ItemTemplate>
<SeparatorTemplate>
,
</SeparatorTemplate>
</asp:Repeater>
];
window.onload = function () {
var mapOptions = {
center: new google.maps.LatLng(41.78768535298007, -99.96481875),
zoom: 7,
mapTypeId: google.maps.MapTypeId.HYBRID
};
var infoWindow = new google.maps.InfoWindow();
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
for (i = 0; i < markers.length; i++) {
var data = markers[i]
var rectangle = new google.maps.Rectangle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
map: map,
bounds: {
north: data.north,
south: data.south,
east: data.east,
west: data.west
}
});
(function (rectangle,data) {
google.maps.event.addListener(rectangle, "click", function (e) {
infoWindow.setContent(data.description);
infoWindow.open(map,rectangle);
});
})(rectangle,data);
}
}
</script>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<div id="dvMap" style="width: 960px; height: 532px"></div>
Any help would be great thanks.
I get a javasript error on your live page: js:31 InvalidValueError: setBounds: not a LatLngBounds or LatLngBoundsLiteral: in property south: not a number. You need to translate the strings in your JSON into numbers before using them to construct google.maps.Rectangle objects.
To open an infowindow on a rectangle, you need to set the position of the infowindow. The syntax infoWindow.open(map, rectangle) doesn't apply to rectangles, that only applies to markers (at least for API objects), see the documentation for more information.
position contains the LatLng at which this info window is anchored. Note: An InfoWindow may be attached either to a Marker object (in which case its position is based on the marker's location) or on the map itself at a specified LatLng. Opening an info window on a marker will automatically update the position.
(function(rectangle, data) {
google.maps.event.addListener(rectangle, "click", function(e) {
infoWindow.setContent(data.description);
infoWindow.setPosition(rectangle.getBounds().getCenter());
infoWindow.open(map);
});
})(rectangle, data);
code snippet:
window.onload = function() {
var mapOptions = {
center: new google.maps.LatLng(41.492537, -99.901813),
zoom: 6,
mapTypeId: google.maps.MapTypeId.HYBRID
};
var infoWindow = new google.maps.InfoWindow();
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < markers.length; i++) {
var data = markers[i]
var rectangle = new google.maps.Rectangle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
map: map,
bounds: {
north: parseFloat(data.north),
south: parseFloat(data.south),
east: parseFloat(data.east),
west: parseFloat(data.west)
}
});
(function(rectangle, data) {
google.maps.event.addListener(rectangle, "click", function(e) {
infoWindow.setContent(data.description);
infoWindow.setPosition(rectangle.getBounds().getCenter());
infoWindow.open(map);
});
})(rectangle, data);
}
}
var markers = [
{
"title": 'Andrews',
"north": '42.75001',
"east": '-103.625',
"south": '42.62501',
"west": '-103.75',
"description": 'Andrews description',
}
,
{
"title": 'Arlington',
"north": '41.50001',
"east": '-96.25001',
"south": '41.37501',
"west": '-96.37501',
"description": '<img src="http://snr.unl.edu/csd-esic/download/geologysoils/digitalgeologicmapscleaned/Arlington/Arlington_Quad.jpg" height="400">',
}
,
{
"title": 'Ashland East',
"north": '41.12501',
"east": '-96.25001',
"south": '41.00001',
"west": '-96.37501',
"description": '<img src="http://snr.unl.edu/csd-esic/download/geologysoils/digitalgeologicmapscleaned/Ashland_East/Ashland_East_Quad.jpg" height="400"">',
}
,
{
"title": 'Beaver Wall',
"north": '43.00001',
"east": '-102.625',
"south": '42.87501',
"west": '-102.75',
"description": 'Beaver Wall description',
}
];
html,
body,
#dvMap {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="dvMap"></div>
I see that geocodezip updated the code in their original answer to the question. Two things are new
First the defining of the bounds applied the function of parseFloat() to each of the coordinates. I am not sure that was necessary since I have been able to get icons or polygons to draw with the coordinates without this function.
I think what really solved the problem was adding the line of code
var bounds = new google.maps.LatLngBounds();
I am not actually sure what this is doing beside defining the variable "bounds" but it seems to have solved my problem.
Thanks geocodezip!
Related
This question already has an answer here:
An issue while showing a path on Google Maps
(1 answer)
Closed 6 years ago.
I'm developing a MVC app using google map API.
There are 4 or more coordinates in my program. According to that I need to draw road path. This is my code so far.
<div id="dvMap" style="width: 500px; height: 500px">
</div>
#section scripts
{
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=AIzaSyBZxYACsC1qz9gticRd4mbki9Tes9qexdw&sensor=false"></script>
<script type="text/javascript">
var markers = [
{
"title": 'Canberra',
"lat": '-35.2809',
"lng": '149.1300',
"description": ''
},
{
"title": 'Sydny',
"lat": '-33.8688',
"lng": '151.2093',
"description": ''
},
{
"title": 'Tamworth',
"lat": '-31.0927',
"lng": '150.9320',
"description": ''
}
,
{
"title": 'Brisbane',
"lat": '-27.465895',
"lng": '153.019519',
"description": ''
}
];
window.onload = function () {
var mapOptions = {
center: new google.maps.LatLng(markers[0].lat, markers[0].lng),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var infoWindow = new google.maps.InfoWindow();
var lat_lng = new Array();
var latlngbounds = new google.maps.LatLngBounds();
for (i = 0; i < markers.length; i++) {
var data = markers[i]
var myLatlng = new google.maps.LatLng(data.lat, data.lng);
lat_lng.push(myLatlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: data.title
});
latlngbounds.extend(marker.position);
(function (marker, data) {
google.maps.event.addListener(marker, "click", function (e) {
infoWindow.setContent(data.description);
infoWindow.open(map, marker);
});
})(marker, data);
}
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);
//***********ROUTING****************//
//Initialize the Path Array
var path = new google.maps.MVCArray();
//Initialize the Direction Service
var service = new google.maps.DirectionsService();
//Set the Path Stroke Color
var poly = new google.maps.Polyline({ map: map, strokeColor: '#4986E7' });
//Loop and Draw Path Route between the Points on MAP
for (var i = 0; i < lat_lng.length; i++) {
if ((i + 1) < lat_lng.length) {
var src = lat_lng[i];
var des = lat_lng[i + 1];
path.push(src);
poly.setPath(path);
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function (result, status) {
if (status == google.maps.DirectionsStatus.OK) {
console.log('len ' + result.routes[0].overview_path.length)
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
});
}
}
}
</script>
}
The problem is the map is shown straight lines as well.
I need to remove straight lines from the map (should keep lines draw on road path) and what's wrong in my code? In addition, Markers should show only for starting point and destination point. But all points are shown as markers. So how to do it...? Please give me a direction for doing it....
At the beginning of your script you're drawing markers on the map. To avoid that comment out the line map: map,
var marker = new google.maps.Marker({
position: myLatlng,
// map: map,
title: data.title
});
To remove the straight lines from the map:
comment out the line
//poly.setPath(path);
You need to use a DirectionsRenderer to show routes on the map once the routes are returned by the directionsService.
Define a function to render the computed routes
function renderDirections(result) {
var directionsRenderer = new google.maps.DirectionsRenderer;
directionsRenderer.setMap(map);
directionsRenderer.setDirections(result);
};
Add the rendering to the callback function of the directionsService
directionsService.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(result, status) {
// if route is computed successfully, render it on map
if (status == google.maps.DirectionsStatus.OK) {
console.log('len ' + result.routes[0].overview_path.length);
renderDirections(result);
} else {
console.log("Error: ", status);
}
});
The issue here is that you're trying to display multiple routes on your map, check this question for details.
Hope this helps.
I know this question has been answered before, but unfortunately, all links to demos/explanation pages are dead at the moment.
I would like to use the Google Maps API V3 to plot two directions (one for driving and one for walking) on the same map. If possible, I would like to use Google's default 'directions' lines, since these look nicer than the polylines.
Does anybody know how to do this? Any help is greatly appreciated!
Here is an example that I have made in the past for this. The trick is multiple DirectionsRenderer instances.
var MAP,
DIRECTIONSRENDERER1,
DIRECTIONSRENDERER2,
USER,
PLACE1,
PLACE2;
function displayDirections1(result, status) {
DIRECTIONSRENDERER1.setDirections(result)
}
function displayDirections2(result, status) {
DIRECTIONSRENDERER2.setDirections(result)
}
function getDirections(location, displayCallback) {
//https://developers.google.com/maps/documentation/javascript/3.exp/reference#DirectionsRequest
var request = {
travelMode: google.maps.TravelMode.DRIVING,
origin: USER,
destination: location
};
//https://developers.google.com/maps/documentation/javascript/3.exp/reference#DirectionsService
var service = new google.maps.DirectionsService();
service.route(request, displayCallback);
}
//Set up the map
function initialize() {
var mapOptions = {
zoom: 6,
//I used the center of the USA
center: new google.maps.LatLng(38.8282, -98.5795)
};
//Make the map
MAP = new google.maps.Map(document.getElementById('map'), mapOptions);
DIRECTIONSRENDERER1 = new google.maps.DirectionsRenderer({
map: MAP
})
DIRECTIONSRENDERER2 = new google.maps.DirectionsRenderer({
map: MAP
})
//Make marker for User location
//NOTE: for testing, the user position is fixed
USER = new google.maps.LatLng(38.8282, -98.5795);
new google.maps.Marker({
label: 'U',
cursor: "User Location",
position: USER,
map: MAP
});
//used for this demo
document.getElementById("latitude").textContent = USER.lat();
document.getElementById("longitude").textContent = USER.lng();
//Make marker for Place1 (location is arbitrary)
PLACE1 = new google.maps.LatLng(37, -97);
new google.maps.Marker({
label: '1',
cursor: "Place 1",
position: PLACE1,
map: MAP
});
//Make marker for Place2 (location is arbitrary)
PLACE2 = new google.maps.LatLng(39, -102);
new google.maps.Marker({
label: '2',
cursor: "Place 2",
position: PLACE2,
map: MAP
});
document.getElementById("p1button").addEventListener("click", function(e) {
getDirections(PLACE1, displayDirections1);
});
document.getElementById("p2button").addEventListener("click", function(e) {
getDirections(PLACE2, displayDirections2);
});
//Trigger map redraw when dom element is resized
google.maps.event.addDomListener(window, 'resize', function() {
google.maps.event.trigger(MAP, 'resize');
});
//Preserve map perspective when after resize
google.maps.event.addListener(MAP, 'resize', function() {
var center = MAP.getCenter();
google.maps.event.addListenerOnce(MAP, 'center_changed', function() {
MAP.setCenter(center);
});
});
}
//runs the code to set up demo
initialize();
html,
body,
#map {
height: 100%;
width: 100%;
border-width: 0;
margin: 0;
padding: 0;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<b>Your location:</b>
<br/>
<span>Latitude: </span><span id="latitude"></span>
<br/>
<span>Longitude: </span><span id="longitude"></span>
<br/>
<br/>
<button id="p1button">Directions to Place1</button>
<button id="p2button">Directions to Place2</button>
<div id="map"></div>
I am loading a data layer in a google map, over a certain country (it's a drawing over a country):
map.data.addGeoJson(geoJsonObject);
I am pretty sure there isn't, but... is there a way to check that the bounds of the map are inside the bounds of the data layer?
(basically, I want to know, when the user navigates on the map, if the current viewport is inside data layer);
var bounds = this.map.getBounds();
var sw = bounds.getSouthWest();
Maybe I can query the data layer in the position of the south west bound and check for some props. indicating that I am inside that data layer?
Or at least:
Does anyone know a way how to get a certain feature object programmatically, knowing the lat and long?
Here the google maps uses events to get to the feature object:
map.data.addListener('click', function(event) {
event.feature.setProperty('isColorful', true);
});
But I do not want to use events. Is there a method to supply the coordinates of a point and get to the feature object?
Something like:
map.getFeature(lat, long).setProperty('isColorful', true);
google.maps.LatLngBounds.contains function could be utilized for that purpose, but since it accepts a single location, the following solution is suggested:
1) initialize data layer bounds from GeoJSON coordinates:
var dataLayer = map.data;
var layerBounds = new google.maps.LatLngBounds();
//1.collect all coordinates from data layer
dataLayer.forEach(function(f) {
var geometry = f.getGeometry();
processCoordinates(geometry, layerBounds.extend, layerBounds);
});
2) determine whether map bounds are within a layer bounds:
if (layerBounds.contains(map.getBounds().getNorthEast()) && layerBounds.contains(map.getBounds().getSouthWest())) {
//...
}
Working example
In the provided example green colored area will be displayed if map
bounds are within a layer bounds, and the red colored in
the opposite case:
var area;
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 53.349248,
lng: -6.255323
},
zoom: 6,
mapTypeId: google.maps.MapTypeId.TERRAIN
});
displayDataLayer(map);
document.getElementById("btnShow").onclick = function() {
var result = displayDataLayerBoundsArea(map);
};
}
function displayDataLayer(map) {
var dataLayer = map.data;
dataLayer.loadGeoJson('https://gist.githubusercontent.com/vgrem/440708612b574764c309/raw/2a4e2feadc204806440c51a14c2ef1f54f4fc3d8/Census2011_Province_generalised20m.json');
dataLayer.setMap(map);
}
function displayDataLayerBoundsArea(map) {
var dataLayer = map.data;
var layerBounds = new google.maps.LatLngBounds();
//1.collect all coordinates from data layer
dataLayer.forEach(function(f) {
var geometry = f.getGeometry();
processCoordinates(geometry, layerBounds.extend, layerBounds);
});
if (area != null) {
area.setMap(null);
}
//2.determine whether map bounds are contained within a layer bounds
if (layerBounds.contains(map.getBounds().getNorthEast()) && layerBounds.contains(map.getBounds().getSouthWest())) {
//map.fitBounds(bounds);
area = new google.maps.Rectangle({
strokeColor: '#00FF00',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#00FF00',
fillOpacity: 0.35,
map: map,
bounds: {
north: layerBounds.getNorthEast().lat(),
south: layerBounds.getSouthWest().lat(),
east: layerBounds.getNorthEast().lng(),
west: layerBounds.getSouthWest().lng()
}
});
} else {
//map.fitBounds(bounds);
area = new google.maps.Rectangle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
bounds: {
north: layerBounds.getNorthEast().lat(),
south: layerBounds.getSouthWest().lat(),
east: layerBounds.getNorthEast().lng(),
west: layerBounds.getSouthWest().lng()
}
});
}
}
function processCoordinates(geometry, callback, thisArg) {
if (geometry instanceof google.maps.LatLng) {
callback.call(thisArg, geometry);
} else if (geometry instanceof google.maps.Data.Point) {
callback.call(thisArg, geometry.get());
} else {
geometry.getArray().forEach(function(g) {
processCoordinates(g, callback, thisArg);
});
}
}
#map {
width: 800px;
height: 640px;
}
<button id="btnShow">Show</button>
<div id="map"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
JSFiddle
I created a map with Google Map Maker. I did so by imported 5 different Excel files that had address fields and saved them all as different layers. The map now has about 500 addresses which are marked with pins that are color coded to the layer they belong with. I have no code per say, just the my Google Map which I created.
Is there anyway I can either use the "Draw Line" tool or another means to select a group of those markers/pins? Ideally I am envisioning being able to draw a shape around them and then being able to select those address to save them as a new data table or layer to export back to Excel.
Does anyone know of a way to achieve this? Even if it is another product then Google Maps? Thank you so much any help would be a life saver.
Something like this.
<head>
<style>
html, body, #map-canvas {
height: 400px;
margin: 0px;
padding: 0px
}
</style>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<script>
var random_marker_locations = [
new google.maps.LatLng(50.7, 4.1),
new google.maps.LatLng(50.4, 4.2),
new google.maps.LatLng(50.1, 4.3),
new google.maps.LatLng(50.8, 4.4),
new google.maps.LatLng(50.5, 4.5),
new google.maps.LatLng(50.2, 4.6),
new google.maps.LatLng(50.9, 4.7),
new google.maps.LatLng(50.6, 4.8),
new google.maps.LatLng(50.3, 4.9)
]
var map;
var markers = [];
var polygon;
var polygonMarkers = [];
var polygonLocations = [];
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(50.40, 4.34), // Brussels, Belgium
mapTypeId: google.maps.MapTypeId.ROADMAP
};
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// add markers
for(var i in random_marker_locations) {
var marker = new google.maps.Marker({position: random_marker_locations[i], map: map, title: 'marker ' + i});
markers.push(marker);
}
// add a click on map event
google.maps.event.addListener(map, 'click', function(e) {
// set a marker there, with a small measle icon
var position = e.latLng;
polygonLocations.push(position);
polygonMarkers.push(new google.maps.Marker({
icon: 'https://maps.gstatic.com/intl/en_ALL/mapfiles/markers2/measle.png',
position: position,
map: map
}));
// now let's add a polygon
drawPolygon(polygonLocations);
});
}
// draws a polygon
function drawPolygon(points) {
if(points.length < 3) {
return;
}
// first delete the previous polygon
if(polygon) {
polygon.setMap(null);
}
// #see https://developers.google.com/maps/documentation/javascript/examples/polygon-simple
polygon = new google.maps.Polygon({
paths: points,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map
});
// display to input
displaySelectedMarkers(polygon);
}
// display the selected markers to input.
function displaySelectedMarkers(polygon) {
// empty the input
document.getElementById('selected_markers').value = '';
var a=0; // I use this to set a comma between the values, but no comma at the end
for(var i in random_marker_locations) {
// #see https://developers.google.com/maps/documentation/javascript/examples/poly-containsLocation
if (google.maps.geometry.poly.containsLocation(random_marker_locations[i], polygon)) {
document.getElementById('selected_markers').value += (a++>0 ? ', ' : '') + i ;
}
}
}
function clearSelection() {
if(polygon) {
polygon.setMap(null);
}
for (var i in polygonMarkers) {
polygonMarkers[i].setMap(null);
}
polygonLocations = [];
document.getElementById('selected_markers').value = '';
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
<hr>
<input id="selected_markers"><br>
<input type="button" onclick="clearSelection()" value="Clear polygon"><br>
Click to select a polygon selection around the markers
</body>
I'm trying to create a map where I can draw a polygon & show it's area & coordinates in the infowindow.
Below is what I have, I'm stuck at the displaying of area & co-ordinates inside the infowindow.
Link to code
code snippet:
var map, infoWindow, drawingManager;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
infoWindow = new google.maps.InfoWindow();
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.POLYGON
]
},
polygonOptions: {
fillColor: '#ffff00',
fillOpacity: 1,
strokeWeight: 5,
clickable: false,
editable: true,
zIndex: 1
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'polygoncomplete', function(polygon) {
openInfoWindowPolygon(polygon);
});
}
function openInfoWindowPolygon(polygon) {
var vertices = polygon.getPath();
var contents = "z";
var bounds = new google.maps.LatLngBounds();
vertices.forEach(function(xy, i) {
bounds.extend(xy);
});
infoWindow.setContent(contents);
infoWindow.setPosition(bounds.getCenter());
drawingManager.setDrawingMode(null);
infoWindow.open(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=drawing"></script>
<div id="map-canvas"></div>
Using the Google Maps Geometry Library, there are functions that allow for computation of area.
function openInfoWindowPolygon(polygon) {
var vertices = polygon.getPath();
var contents = "<b>Vertices:</b><ol>";
vertices.forEach(function(vert, index){contents += "<li>"+vert.toString()+"</li>"});
contents += "</ol><b>Area:</b>"+google.maps.geometry.spherical.computeArea(vertices);
infoWindow.setContent(contents);
var bounds = new google.maps.LatLngBounds();
vertices.forEach(function(xy,i){
bounds.extend(xy);
});
infoWindow.setPosition(bounds.getCenter());
drawingManager.setDrawingMode(null);
infoWindow.open(map);
}
This code compiles the vertices into an <ol>, and then adds the area underneath.