how to inject holes in google maps polyline objects? - polyline

As shown in the below linked example, polygons support configuration of holes by providing outer and inner coordinates separately. Is there any such option in polylines?
Polygon With Hole
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 5,
center: { lat: 24.886, lng: -70.268 },
});
// Define the LatLng coordinates for the polygon's outer path.
const outerCoords = [
{ lat: 25.774, lng: -80.19 },
{ lat: 18.466, lng: -66.118 },
{ lat: 32.321, lng: -64.757 },
];
// Define the LatLng coordinates for the polygon's inner path.
// Note that the points forming the inner path are wound in the
// opposite direction to those in the outer path, to form the hole.
const innerCoords = [
{ lat: 28.745, lng: -70.579 },
{ lat: 29.57, lng: -67.514 },
{ lat: 27.339, lng: -66.668 },
];
// Construct the polygon, including both paths.
const bermudaTriangle = new google.maps.Polygon({
paths: [outerCoords, innerCoords],
strokeColor: "#FFC107",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FFC107",
fillOpacity: 0.35,
});
bermudaTriangle.setMap(map);
}
window.initMap = initMap;

Related

Google Map v3 API: "InvalidValueError: setPosition: not a LatLng or LatLngLiteral: in property lat: not a number"

I have been getting the "InvalidValueError: setPosition: not a LatLng or LatLngLiteral: in property lat: not a number" message and have reviewed previous posts but can't seem to find which line is causing the issue.
The below code seems to work but throws the above warning. I have tried parseFloat on lat and long values and on setPosition value but no joy.
const flightPlanCoordinates1100_0 = [{
lat: 51.52386762,
lng: -0.059058666
},
{
lat: 51.52394638,
lng: -0.058520453
},
{
lat: 51.52716833,
lng: -0.05617915
}, {
lat: 51.54674506,
lng: -0.059390801
},
];
// define the polyline attributes
const flightPath1100_0 = new google.maps.Polyline({
path: flightPlanCoordinates1100_0,
geodesic: true,
strokeColor: "Aqua",
strokeOpacity: 1.0,
strokeWeight: 2,
draggable: true,
map: map
});
// create an invisible marker for the label listener
labelMarker = new google.maps.Marker({
position: flightPath1100_0,
map: map,
visible: false
});
var myLabel = new Label();
// lets add an event listener, if you move the mouse over the line, it will tell you the track id
flightPath1100_0.addListener('mouseover', function(e) {
labelMarker.setPosition(e.latLng)
myLabel.bindTo('position', labelMarker, 'position');
// Type the Track Id name here, this can be loaded using excel macro
myLabel.set('text', "1100");
myLabel.setMap(map);
});
flightPath1100_0.setMap(map);
google.maps.event.addDomListener(window, 'load', initialize);
}
The issue as MrUpsidDown pointed out was that the position was not in latlng format, the below changes seemed to have worked
labelMarker = new google.maps.Marker({
position: new google.maps.LatLng(flightPath1100_0),
map: map,
visible: false
});

InfoWindow Undefined Google maps API

I want to get the content property of the array place of interest, so below the if marker.content is giving me undefined then I create the new google.maps.InfoWindow
Code:
var map = null;
placesOfInterest = [
{ name: 'Charme da paulista', lat: -23.562172, lng: -46.655794, content:'<h1>Charme</h1>' },
{ name: 'The Blue Pub', lat: -23.563112, lng: -46.650338, content:'<h1>The Blue Pub</h1>' },
{ name: 'Veloso', lat: -23.585107, lng: -46.635219 },
{ name: 'Let\'s Beer', lat: -23.586508, lng: -46.641739 },
{ name: 'O\'Malley\'s', lat: -23.558296, lng: -46.665923 },
{ name: 'Finnegan\'s', lat: -23.559547, lng: -46.676794 },
{ name: 'Partisans', lat: -23.561049, lng: -46.682555 },
{ name: 'Morrison', lat: -23.555106, lng: -46.690883 },
{ name: 'Cão Véio', lat: -23.558130, lng: -46.679508 },
{ name: 'Cervejaria Nacional', lat: -23.564740, lng: -46.690641 },
{ name: 'Brewdog', lat: -23.561309, lng: -46.693935 },
{ name: 'Rei das Batidas', lat: -23.570613, lng: -46.705977 }
];
const customIcon = {
path: 'M0-48c-9.8 0-17.7 7.8-17.7 17.4 0 15.5 17.7 30.6 17.7 30.6s17.7-15.4 17.7-30.6c0-9.6-7.9-17.4-17.7-17.4z',
fillColor: '#F7B217',
fillOpacity: 0.98,
scale: 0.98,
strokeColor: '#666666',
strokeWeight: 3
};
function addMarker(marker) {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(marker.lat, marker.lng),
icon: customIcon,
title: marker.name,
});
if(marker.content){
var infoWindow = new google.maps.InfoWindow({
content:marker.content
});
marker.addListener('click',function(){
infoWindow.open(map, marker)
});
}
}
function initMap() {
var mapOptions = {
center: new google.maps.LatLng(-23.562172, -46.655794),
gestureHandling: 'greedy',
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP]
},
disableDefaultUI: true,
scaleControl: true,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.DEFAULT,
}
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
//Adicionando o primeiro marcador como exemplo
for(var i = 0;i< placesOfInterest.length;i++ ){
addMarker(placesOfInterest[i]);
}
}
In your addMarker function, you are overwriting the input marker data with a new google.maps.Marker object, so the marker.content property never exists.
Rename either the input argument or the internal marker variable to avoid the conflict:
function addMarker(marker) {
var gmarker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(marker.lat, marker.lng),
icon: customIcon,
title: marker.name,
});
if(marker.content){
var infoWindow = new google.maps.InfoWindow({
content:marker.content
});
gmarker.addListener('click',function(){
infoWindow.open(map, gmarker)
});
}
}
proof of concept fiddle
code snippet:
var map = null;
var placesOfInterest = [{
name: 'Charme da paulista',
lat: -23.562172,
lng: -46.655794,
content: '<h1>Charme</h1>'
}
];
const customIcon = {
path: 'M0-48c-9.8 0-17.7 7.8-17.7 17.4 0 15.5 17.7 30.6 17.7 30.6s17.7-15.4 17.7-30.6c0-9.6-7.9-17.4-17.7-17.4z',
fillColor: '#F7B217',
fillOpacity: 0.98,
scale: 0.98,
strokeColor: '#666666',
strokeWeight: 3
};
function addMarker(marker) {
var gmarker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(marker.lat, marker.lng),
icon: customIcon,
title: marker.name,
});
if (marker.content) {
var infoWindow = new google.maps.InfoWindow({
content: marker.content
});
gmarker.addListener('click', function() {
infoWindow.open(map, gmarker)
});
}
}
function initMap() {
var mapOptions = {
center: new google.maps.LatLng(-23.562172, -46.655794),
gestureHandling: 'greedy',
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP]
},
disableDefaultUI: true,
scaleControl: true,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.DEFAULT,
}
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
//Adicionando o primeiro marcador como exemplo
for (var i = 0; i < placesOfInterest.length; i++) {
addMarker(placesOfInterest[i]);
}
}
html,
body,
#map {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>

center and fit boundaries of geojson multiple polygon data

I am trying to center and fit the boundaries of multiple geojson polygon features on my google.maps.Map.
See this non geojson fiddle recreating the effect i'm after.
Is there an easy Google Map API 3 function to do this for geojson data?
See my code below and fiddle here
var map;
window.initMap = function() {
var mapProp = {
center: new google.maps.LatLng(51.8948201,-0.7333298),
zoom: 17,
mapTypeId: 'satellite'
};
map = new google.maps.Map(document.getElementById("map"), mapProp);
map.data.loadGeoJson('https://api.myjson.com/bins/g0tzw');
map.data.setStyle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
var bounds = new google.maps.LatLngBounds();
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
}
I need expert pointers on cleanest and best way approach this.
See working demo of my code above in fiddle.
http://jsfiddle.net/joshmoto/fe2vworc/
I've included my geojson inline so you can see the polygons on the map.
Here is a quick example of how you can get your features bounds. This will just get each feature bounds, extend a LatLngBounds object and then fit the map with these bounds.
var map;
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 10,
center: {
lat: 0,
lng: 0
}
});
var permits = {
type: "FeatureCollection",
id: "permits",
features: [{
type: "Feature",
properties: {
name: "Alpha Field"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-0.72863, 51.895995],
[-0.730022, 51.896766],
[-0.730754, 51.896524],
[-0.731234, 51.896401],
[-0.731832, 51.896294],
[-0.732345, 51.896219],
[-0.732945, 51.896102],
[-0.732691, 51.895774],
[-0.732618, 51.895531],
[-0.732543, 51.895359],
[-0.73152, 51.894751],
[-0.731037, 51.894488],
[-0.730708, 51.894324],
[-0.72863, 51.895995]
]
]
}
},
{
type: "Feature",
properties: {
name: "Beta Field"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-0.728004, 51.895658],
[-0.72863, 51.895995],
[-0.730708, 51.894324],
[-0.731217, 51.893784],
[-0.730992, 51.893709],
[-0.730793, 51.893567],
[-0.730734, 51.893435],
[-0.730761, 51.89333],
[-0.729696, 51.893244],
[-0.729391, 51.89314],
[-0.729249, 51.893586],
[-0.728991, 51.894152],
[-0.728525, 51.894983],
[-0.728004, 51.895658]
]
]
}
}
]
};
google.maps.event.addListenerOnce(map, 'idle', function() {
// Load GeoJSON.
map.data.addGeoJson(permits);
// Create empty bounds object
var bounds = new google.maps.LatLngBounds();
// Loop through features
map.data.forEach(function(feature) {
var geo = feature.getGeometry();
geo.forEachLatLng(function(LatLng) {
bounds.extend(LatLng);
});
});
map.fitBounds(bounds);
});
}
initialize();
#map-canvas {
height: 150px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
Props to #MrUpsidown for providing the working method to fitBounds.
I'm posting this answer to show my final solution based on #MrUpsidown answer using GeoJson data via loadGeoJson()
Here is my readable GeoJson here http://myjson.com/g0tzw
// initiate map
window.initMap = function() {
// permits json
var permits = 'https://api.myjson.com/bins/g0tzw';
// map properties
var mapProp = {
zoom: 17,
mapTypeId: 'satellite'
};
// google map object
var map = new google.maps.Map(document.getElementById("map"), mapProp);
// load GeoJSON.
map.data.loadGeoJson(permits, null, function () {
// create empty bounds object
var bounds = new google.maps.LatLngBounds();
// loop through features
map.data.forEach(function(feature) {
var geo = feature.getGeometry();
geo.forEachLatLng(function(LatLng) {
bounds.extend(LatLng);
});
});
// fit data to bounds
map.fitBounds(bounds);
});
// map data styles
map.data.setStyle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
}
I'm calling initMap via...
<script async defer src="https://maps.googleapis.com/maps/api/js?key=<?=$gmap_api?>&callback=initMap"></script>
See working demo here.
http://jsfiddle.net/joshmoto/eg3vj17m/

Google Maps - infoWindow on mouseover of polygon

I created a polygon area on this page
I need to create an infoWindow that opens on mouseover. I found information on opening an infoWindow on mouseclick on markers but not on a polygon area.
<div id="map"></div>
<script>
// This is a simple polygon representing the MRPD Rescue Zone.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
center: {lat: -16.4836, lng: 145.4653},
mapTypeId: 'terrain'
});
// Definition of the LatLng coordinates for the polygon's path.
var polygonCoords = [
{lat: -16.4836, lng: 145.4653},
{lat: -16.4500, lng: 145.4133},
{lat: -16.2319, lng: 145.4763},
{lat: -16.0878, lng: 145.4548},
{lat: -16.0454, lng: 145.9000},
{lat: -16.4861, lng: 146.1269},
{lat: -16.7229, lng: 145.6500},
{lat: -16.5913, lng: 145.5192},
];
// Construction of polygon.
var mrpdPolygon = new google.maps.Polygon({
paths: polygonCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.6,
strokeWeight: 1,
fillColor: '#FF0000',
fillOpacity: 0.10
});
mrpdPolygon.setMap(map);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=API_Key&callback=initMap">
</script>
add a mouseover and mouseout event to the polygon:
function mousefn(evt) {
infowindow.setContent("polygon<br>coords:" + bounds.getCenter().toUrlValue(6));
infowindow.setPosition(bounds.getCenter()); // or evt.latLng
infowindow.open(map);
}
google.maps.event.addListener(mrpdPolygon, 'mouseover', mousefn);
google.maps.event.addListener(mrpdPolygon, 'mouseout', function(evt) {
infowindow.close();
infowindow.opened = false;
});
proof of concept fiddle
code snippet:
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<div id="map"></div>
<script>
// This is a simple polygon representing the MRPD Rescue Zone.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
center: {
lat: -16.4836,
lng: 145.4653
},
mapTypeId: 'terrain'
});
// Construction of polygon.
var mrpdPolygon = new google.maps.Polygon({
paths: polygonCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.6,
strokeWeight: 1,
fillColor: '#FF0000',
fillOpacity: 0.10
});
mrpdPolygon.setMap(map);
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < mrpdPolygon.getPath().getLength(); i++) {
bounds.extend(mrpdPolygon.getPath().getAt(i));
}
var infowindow = new google.maps.InfoWindow();
infowindow.opened = false;
function mousefn(evt) {
infowindow.setContent("polygon<br>coords:" + bounds.getCenter().toUrlValue(6));
infowindow.setPosition(bounds.getCenter());
infowindow.open(map);
}
google.maps.event.addListener(mrpdPolygon, 'mouseover', mousefn);
// google.maps.event.addListener(mrpdPolygon, 'mousemove', mousefn);
google.maps.event.addListener(mrpdPolygon, 'mouseout', function(evt) {
infowindow.close();
infowindow.opened = false;
});
}
// Definition of the LatLng coordinates for the polygon's path.
var polygonCoords = [{
lat: -16.4836,
lng: 145.4653
},
{
lat: -16.4500,
lng: 145.4133
},
{
lat: -16.2319,
lng: 145.4763
},
{
lat: -16.0878,
lng: 145.4548
},
{
lat: -16.0454,
lng: 145.9000
},
{
lat: -16.4861,
lng: 146.1269
},
{
lat: -16.7229,
lng: 145.6500
},
{
lat: -16.5913,
lng: 145.5192
},
];
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
you will add mouseover event to the div id "map"
JavaScript code:
//Select html element
const mapInfo = document.querySelector("#map");
//add mouseover event to the selected element
mapInfo.addEventListener ('mouseover', initMap);
Visit this https://developers.google.com/maps/documentation/javascript/infowindows link for more information. I hope this helps.

Show radius when click on marker

I want to click on the google marker which will show the google circle (radius). Not sure if the placement of addListener is wrong or am I missing some stuff.
coordinates = [
['Tan Tock Seng Hospital', {lat: 1.3213762, lng: 103.8457089}],
['Singapore General Hospital', {lat: 1.279421747, lng: 103.8345482}],
['Changi General Hospital', {lat: 1.340825885, lng: 103.9494655}],
['Khoo Teck Puat Hospital', {lat: 1.424081019, lng: 103.838578}],
['Ng Teng Fong General Hospital', {lat: 1.333463114, lng: 103.7455669}],
['National University Hospital', {lat: 1.29442026, lng: 103.7836869}]
];
for (var i = 0; i < coordinates.length; i++) {
// Google Marker for Hospital Coordinates
marker = new google.maps.Marker({
position: coordinates[i][1],
map: map,
icon: 'https://maps.google.com/mapfiles/kml/paddle/blu-stars.png',
title: coordinates[i][0]
});
marker_radius = new google.maps.Circle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0,
map: map,
center: coordinates[i][1],
radius: 2000, // in metres
clickable: false
});
marker_radius.setVisible(true); // set circle to invisible
marker_radius.bindTo('center', marker, 'position'); // binds the circle to marker
google.maps.event.addListener(marker, 'click', function() {
marker_radius.setVisible(getVisible() ? false : true);
});
}
You need to use a closure in your event listener:
google.maps.event.addListener(marker, 'click', (function(marker, marker_radius) {
return function () {
marker_radius.setVisible(marker_radius.getVisible() ? false : true);
}
})(marker, marker_radius));
Read here for more information.
Also your Javascript console should tell you that getVisible() is not defined. So you need to change it to marker_radius.getVisible().

Resources