Reputation: 937
A client has loaded some polygons onto a map using Google Maps APIv3 loadGeoJson()
method. I want to be able to search through those polygons and, when one matches a submitted string, zoom/centre on it and trigger a click
event, opening the infowindow of that polygon.
Some answers hint that, to reference the geoJSON feature, it's best to use getId()
, then use that reference to select the polygon on the map. Comes out undefined
, and not sure if it would help anyways; few other methods really seem to work (getGeometry()
is broken), through getProperty()
does. This makes me think maybe I'm iterating over the wrong array.
This JSBin illustrates what I'm trying to do, especially lines 85-100:
// Trying to search in the layer and trigger an event
geoJsonLayer.forEach(function(feature) {
if(searchString===feature.getProperty('letter')) {
// Match found, Zoom to this feature and pop its infobox
var foundFeatureId = feature.getId(); // Is undefined
// var foundFeatureId = feature.id; // Is undefined
// var foundFeatureGeo = feature.getGeometry().get(); // Not a function
console.log(foundFeatureId);
google.maps.event.trigger(map,'click',feature); // seems to do nothing
}
});
On search of a character ("g","o","l", for instance), the search finds a match and then tries to trigger the click event of that geoJSON polygon (ultimately, so the infowindow is opened).
This is the part that's stumping me. I've tried defining the ID, but it's undefined using getId()
. Can't seem to directly trigger it either when iterating over the Data layer. Can't seem to find it when trying to look into maps.data
either.
How do I properly trigger this event using the geoJSON layer only?
Upvotes: 4
Views: 4233
Reputation: 161404
A google.maps.Data.Polygon
doesn't have a get()
method, it has a getArray()
method, which returns an array of the contained Data.LinearRings. So for the "o" it will have 2 entries, for the "G" it will only have one.
This will zoom the map to fit a polygon based on its "letter" property:
geoJsonLayer.forEach(function(feature) {
if(searchString===feature.getProperty('letter')) {
var foundFeatureGeo = feature.getGeometry().getAt(0).getArray(); // Also broken
var bounds = new google.maps.LatLngBounds();
for (var i=0; i<foundFeatureGeo.length; i++) {
bounds.extend(foundFeatureGeo[i]);
}
map.fitBounds(bounds);
}
To open an infowindow you need to determine where you want it to open. There is no access to a google.maps.Polygon
to trigger a click on, and to trigger it on the DataLayer, you need to provide the "event data", both the .feature
and the latLng
properties of the event.
var name = feature.getProperty('letter');
var myHTMLss = '<table>' +
'<tr><td>Name:</td><td>'+name+'</td></tr>' +
'</table>';
infowindow.setContent(myHTMLss);
// arbirarily pick the first point
infowindow.setPosition(foundFeatureGeo[0]);
infowindow.open(map);
code snippet:
// Loading stuff
function initMap() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 4,
center: {
lat: -28,
lng: 137
},
mapTypeId: google.maps.MapTypeId.SATELLITE
});
// Load geoJSON
geoJsonLayer = new google.maps.Data();
geoJsonLayer.addGeoJson(sampleJSON);
geoJsonLayer.setMap(map);
// Set click event for infowindow
var infowindow = new google.maps.InfoWindow();
geoJsonLayer.addListener('click', function(event) {
var name = event.feature.getProperty('letter');
var myHTMLss = '<table>' +
'<tr><td>Name:</td><td>' + name + '</td></tr>' +
'</table>';
infowindow.setContent(myHTMLss);
infowindow.setPosition(event.latLng);
infowindow.open(map);
});
// Search for property in geoJson
$('#search').click(function() {
var searchString = $('#searchInput').val();
// Search in the layer and trigger an event
geoJsonLayer.forEach(function(feature) {
if (searchString === feature.getProperty('letter')) {
// Zoom to this feature and pop its infobox
var foundFeatureGeo = feature.getGeometry().getAt(0).getArray();
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < foundFeatureGeo.length; i++) {
bounds.extend(foundFeatureGeo[i]);
}
map.fitBounds(bounds);
google.maps.event.trigger(geoJsonLayer, 'click', {
// arbirarily pick the first point of the outer ring of the polygon
latLng: foundFeatureGeo[0],
"feature": feature
});
}
});
});
}
google.maps.event.addDomListener(window, 'load', initMap);
var sampleJSON = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"letter": "G",
"color": "blue",
"rank": "7",
"ascii": "71",
"id": 0
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[123.61, -22.14],
[122.38, -21.73],
[121.06, -21.69],
[119.66, -22.22],
[119.00, -23.40],
[118.65, -24.76],
[118.43, -26.07],
[118.78, -27.56],
[119.22, -28.57],
[120.23, -29.49],
[121.77, -29.87],
[123.57, -29.64],
[124.45, -29.03],
[124.71, -27.95],
[124.80, -26.70],
[124.80, -25.60],
[123.61, -25.64],
[122.56, -25.64],
[121.72, -25.72],
[121.81, -26.62],
[121.86, -26.98],
[122.60, -26.90],
[123.57, -27.05],
[123.57, -27.68],
[123.35, -28.18],
[122.51, -28.38],
[121.77, -28.26],
[121.02, -27.91],
[120.49, -27.21],
[120.14, -26.50],
[120.10, -25.64],
[120.27, -24.52],
[120.67, -23.68],
[121.72, -23.32],
[122.43, -23.48],
[123.04, -24.04],
[124.54, -24.28],
[124.58, -23.20],
[123.61, -22.14]
]
]
}
}, {
"type": "Feature",
"properties": {
"letter": "o",
"color": "red",
"rank": "15",
"ascii": "111",
id: 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[128.84, -25.76],
[128.18, -25.60],
[127.96, -25.52],
[127.88, -25.52],
[127.70, -25.60],
[127.26, -25.79],
[126.60, -26.11],
[126.16, -26.78],
[126.12, -27.68],
[126.21, -28.42],
[126.69, -29.49],
[127.74, -29.80],
[128.80, -29.72],
[129.41, -29.03],
[129.72, -27.95],
[129.68, -27.21],
[129.33, -26.23],
[128.84, -25.76]
],
[
[128.45, -27.44],
[128.32, -26.94],
[127.70, -26.82],
[127.35, -27.05],
[127.17, -27.80],
[127.57, -28.22],
[128.10, -28.42],
[128.49, -27.80],
[128.45, -27.44]
]
]
}
}]
};
html,
body,
#map-canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<input type="text" id="searchInput" />
<button id="search">Search</button>
<div id="map-canvas"></div>
Upvotes: 3
Reputation: 6158
Trigger click
event to map.data
like below.
(In the below code, I add a polygon instead of loading geojson file, in order to test anyone without file)
update: searching a feature, use map.data.forEach()
method.
update2: Case of a custom layer.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style type="text/css">
#map_canvas {
width: 600px;
height: 400px;
border: 1px solid gray;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script>
function initMap() {
var div = document.getElementById("map_canvas");
var map = new google.maps.Map(div, {
center: {lat: 41.79763176991999, lng: 140.75910257175565},
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
//map.data.loadGeoJson("polygons.json");
//----------------------------------------------
// Start - Adding a feature (instead of loadGeoJson for test)
//----------------------------------------------
// polygon paths
var exteriorBoundary = new google.maps.Data.LinearRing([
{lat: 41.79567213554726, lng: 140.75482176616788},
{lat: 41.795888098191426, lng: 140.75384544208646},
{lat: 41.79604007146779, lng: 140.75370596721768},
{lat: 41.79621604007439, lng: 140.75369523838162},
{lat: 41.79739981632479, lng: 140.7546071894467},
{lat: 41.79878352706213, lng: 140.75461791828275},
{lat: 41.79895148991592, lng: 140.75470374897122},
{lat: 41.79899947922187, lng: 140.7548968680203},
{lat: 41.798743535841595, lng: 140.75671004131436},
{lat: 41.79915944331544, lng: 140.7585554011166},
{lat: 41.79914344692405, lng: 140.7587699778378},
{lat: 41.79895948813609, lng: 140.75889872387052},
{lat: 41.79763176991999, lng: 140.75910257175565},
{lat: 41.796487990607034, lng: 140.7601754553616},
{lat: 41.79630402419653, lng: 140.76018618419766},
{lat: 41.79618404581822, lng: 140.76005743816495},
{lat: 41.79561614511331, lng: 140.75835155323148},
{lat: 41.79444033470146, lng: 140.7573108561337},
{lat: 41.794408339558885, lng: 140.75716065242887},
{lat: 41.79443233591732, lng: 140.75695680454373},
{lat: 41.795024243248456, lng: 140.75621651485562},
{lat: 41.79467229900768, lng: 140.7550578005612},
{lat: 41.794736289013386, lng: 140.7548968680203},
{lat: 41.79567213554726, lng: 140.75482176616788}
]);
var polygon = new google.maps.Data.Polygon([exteriorBoundary]);
var feature = new google.maps.Data.Feature({
geometry: polygon,
properties: {
name: "Goryo-kaku, Hokkaido, Japan"
},
id: "goryokaku"
});
// Add a feature to the data layer.
var layer = new google.maps.Data({
map: map
});
layer.add(feature);
// Fill all polygon as red
layer.setStyle({
scale: 6,
strokeColor: "white",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "red",
fillOpacity: 0.5
});
//----------------------------------------------
// End - adding a feature
//----------------------------------------------
// Catch the click event
layer.addListener('click', function(data_mouseEvent) {
var feature = data_mouseEvent.feature;
feature.toGeoJson(function(geojson){
var infoWnd = new google.maps.InfoWindow({
content: JSON.stringify(geojson.properties, null, 2),
position: feature.getGeometry().getAt(0).getAt(0)
});
infoWnd.open(map);
});
});
layer.forEach(function(feature) {
if (feature.getProperty('name') === "Goryo-kaku, Hokkaido, Japan" ) {
google.maps.event.trigger(layer, 'click', {
feature: feature
});
}
});
}
google.maps.event.addDomListener(window, "load", initMap);
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>
Upvotes: 1