How to access clicked polygon to change it's style in Google Maps Api v3 - google-maps-api-3

I'm using a code similar the one below to display buildings KML Layer. Click event works and i get name and HTML. What i need to do is, I want to change style of the clicked polygon/line. Let say I want to change border width. How can i do that?
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
center: {
lat: 41.876,
lng: -87.624
}
});
var ctaLayer = new google.maps.KmlLayer({
url: 'http://googlemaps.github.io/js-v2-samples/ggeoxml/cta.kml',
map: map
});
ctaLayer.addListener('click', function(kmlEvent) {
//need to change style of the clicked element here.
});
}

You can't change the styling of a KmlLayer using the API.
Options:
use a FusionTablesLayer (import your KML into a FusionTable, you can dynamically style polylines from a FusionTable).
use a 3rd-party KML parser, like geoxml3 or geoxml-v3 to render the KML as native Google Maps JavaScript API v3 polylines, then modify those. Note that the 3rd-party parsers are subject to the same domain security policy for the KML, so can only access KML from other domains through a proxy.
example using geoxml3 (polylines change to yellow on mouseover)

Related

Customize Google Places Map API "icon" InfoWindows

I am having trouble customizing the "clicked" infowindows in the google places API. I am able to use the places api to find locations and to customize the searched infoWindows (image 1) but I cannot seem to figure out how to customize the infoWindows launched by the places icons (image 2).
I apologize, part of my problem is I don't know what those specific infoWindows are called and if I did, I might be able to search for the solution. It seems most questions on this site are related to customizing the searched infoWindow content and I have had success doing that.
Searched Customized InfoWindow (image 1)
The InfoWindow that I want to customize and is launched by icons on the map (image 2)
Those are called clickableIcons. From the documentation
clickableIcons | Type: boolean
When false, map icons are not clickable. A map icon represents a point of interest, also known as a POI. By default map icons are clickable.
and:
getClickableIcons() | Return Value: boolean
Returns the clickability of the map icons. A map icon represents a point of interest, also known as a POI. If the returned value is true, then the icons are clickable on the map.
To control the InfoWindow, stop the default one from being opened, as described in the IconMouseEvent documentation:
google.maps.IconMouseEvent object specification
This object is sent in an event when a user clicks on an icon on the map. The place ID of this place is stored in the placeId member. To prevent the default info window from showing up, call the stop() method on this event to prevent it being propagated. Learn more about place IDs in the Places API developer guide.
proof of concept fiddle
code snippet:
function initialize() {
var map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var iw = new google.maps.InfoWindow();
google.maps.event.addListener(map, 'click', function(evt) {
evt.stop()
if (evt.placeId) {
console.log(evt.placeId);
iw.setContent(evt.placeId);
iw.setPosition(evt.latLng);
iw.open(map);
}
});
}
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<div id="map_canvas"></div>

Get latitude and longitude of mouse click in KML plotted using geoxml3

Is there any way to get the right click event on a parsed KML layer using geoxml3 on google map.I am getting the right click event of map ie outer region of KML. But i am not able to get the click event on the parsed KML.
I have used like this
var geoXml = new geoXML3.parser({
map: map
});
geoXml.parse('file.kml');
geoxml3 parses the KML to native Google Maps Javascript API v3 objects. To add a right click events to them, you need to either add custom createMarker, createPolyline, createPolygon functions that add the right click listeners as the objects are created or process the results and add the listeners to the output.
The following was helpful and got the latitude and longitude when right clicked on a KML layer in google map
var geoXml = new geoXML3.parser({
map: map,
afterParse: function (doc) {
for (var i = 0; i < doc[0].placemarks.length; i++) {
var p = doc[0].placemarks[i];
clickablePolygon(p);
}
}
});
geoXml.parse(parameter.FileName);
function clickablePolygon(p) {
google.maps.event.addListener(
p.polygon,
"rightclick",
function (event) {
var clickedLocation = event.latLng;
var latlng = {
lat: clickedLocation.lat(),
lng: clickedLocation.lng(),
zlevel: map.getZoom()
};
}
);
}

google maps infoWindow click event re-renders map-canvas in Meteor

Hey Im trying to use google maps within my MeteorJS project to have google maps display on a map all customers, and then to display an infoWindow when you click on one of the markers.
problem is anytime you click on the marker it re-renders the map from scratch, i know this has to do with the the reactivity of the Session variable being set when the infoWindow is being clicked.
is there any way avoid the map being re-rendered when the session variable is changing?
thanks.
below is the JS and template im using in my project.
<template name="customers_map">
{{#constant}}
<div id="mapWrapper">
<div id="map-canvas"></div>
</div>
{{/constant}}
</template>
the code for making the google maps and markers.
Template.customers_map.rendered = function() {
$("#map-canvas").height("400px");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(p) {
Session.set("myLat", p.coords.latitude);
Session.set("myLng", p.coords.longitude);
});
}
Deps.autorun(function(){
var mapOptions = {
center: new google.maps.LatLng(Session.get("myLat"), Session.get("myLng")),
zoom: 15,
zoomControl: true,
zoomControlOptions: {style: google.maps.ZoomControlStyle.SMALL},
streetViewControl: false,
mapTypeControl: false,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.SMALL
}
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var infowindow = new google.maps.InfoWindow({
content: Template.customers_infoWindow()
});
Customers.find().forEach(function(customer) {
if (customer.loc != null) {
var geo = customer.geoLocation();
var marker = new google.maps.Marker({
position: new google.maps.LatLng(geo.lat, geo.lng),
title: customer.name(),
icon:'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', function() {
Session.set("customerId", customer._id);
infowindow.open(map,marker);
});
} else {
console.log(customer.name() + " has no geoLocation");
};
});
});
};
the infoWindow template
<template name="customers_infoWindow">
<h1>{{record.name}}</h1>
</template>
and the js for the infoWindow template
Template.customers_infoWindow.record = function() {
return Customers.findOne({_id: Session.get("customerId")});
}
If you create a global googlemaps object, you can access its properties from anywhere. This article has a nice example of doing this.
The overall gist is:
Create a googlemaps class with an initialize method. At the end of the initialize method, set a session variable for your map's existence. ( Session.set('map', true);)
Call create a googlemap object by calling the googlemap init method from within Template.customers_map.rendered.
It's a bit difficult to be sure without having a running version in front of me, but I think this is essentially because you have all your code in one big Deps.autorun block. Clicking one of the markers is changing the Session variable customerId, which will cause customers_infoWindow to re-render (as it's clearly a dependency), but I'm sure this is the intended behaviour.
However, since you're declaring var infoWindow in your Deps.autorun block to have an instance of that template as one of its properties, I think that changing customers_infoWindow will actually invalidate the entire Deps.autorun calculation, which means the whole block will be executed again, including the var map = new google.maps.Map(...) line, which will essentially re-render the map (even though it doesn't re-render that actual div element that contains it).
So, I would suggest splitting your code into separate Deps.autorun blocks, and making sure that anything in the same block should be re-run at the same time - clearly, this means that the Google Maps initialisation code and the infoWindow handler should be in separate blocks.
To reiterate, I think that's what's going on, but you'll have to try it and let me know...

KML layer On/Off for integrated Google Maps 3 & GE application

I have a webmap with GMaps & GEarth integrated, in order for the user to switch between different views.
I load 3 KML files and control their visibility using checkboxes. This example here uses the same function stackOverflowQuestion
When I switch views Map - Satellite - Earth I have my KMLs working on Map & Satellite view, BUT not on Earth View.
function init() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: new google.maps.LatLng(xx, xx),
mapTypeId: google.maps.MapTypeId.TERRAIN
});
googleEarth = new GoogleEarth(map);
google.maps.event.addListenerOnce(map, 'tilesloaded', addOverlays);
}//end init
[...]
function OnOffKML(i) {
if(currentKmlObjects[i].getMap() === null) {
currentKmlObjects[i].setMap(map);
}
else {
currentKmlObjects[i].setMap(null);
}
}
this function works for Google Maps Api 3, but not for Google Earth plugin...
Does this mean I have to use the fetch{} for it to show on GE? Is there a workaround?
Could I exclude my toggleKML{} for the earth view in any way?
OK,
The problem here is that we cannot code for GM Api 3 and expect to have results for GE Api as well.
Sure the two can be integrated but you have to decide that one of the two will have limited functionality.
Thus I decided to split the application up, work separately and efficiently.
As for GE method for KML usage, I have used the fetch{} function, along with checkbox selection.
That is not strictly true, you would just need to reload your Kml into the earth API.
You could modify your OnOffKML function to act differently depending on the current mode (earth/maps).
The problem you have currently is that you are using Google Maps Api methods, on the Google Earth plugin.
Anyhow, something like the following would work, allowing the method to handle both.
function OnOffKML(i) {
if(googleEarth.getWindow().getVisibility()) {
// code for earth api
} else {
// code for maps api
}
}

Google maps KmlLayer times out and InfoWindow not showing

I have a google map embedded in a site that loads a kml file at https://www.getstable.org/who-can-help/therapist-map-kml using KmlLayer. Sometimes the map doesn't load up, I presume because google maps has a strict timeout, and often some of the pins on the map aren't clickable but some are with no clear reason why. Does anyone know what the timeout limit is on kmlLayer and how to increase it? Also is there any reason why sometimes some of the pins aren't clickable (ie no InfoWindow appears when you click a pin and the cursor doesn't change to a hand)?
Here's the code that shows it (some of the fields are templated):
<div id="map_canvas" style="width: 856px;height: 540px;">Loading...</div>
<script type="text/javascript" src="{protocol}://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var the_map = {
options : {
zoom:{embed:zoom_level},
center:new google.maps.LatLng({embed:latitude},{embed:longitude}),
mapTypeId: google.maps.MapTypeId.ROADMAP
},
geocoder : null,
map : null,
init : function() {
this.geocoder = new google.maps.Geocoder();
$('#map_canvas').delegate('a', 'click', function(event) {
window.location.href=$(this).attr('href');
return false;
});
},
load_map : function() {
this.map = new google.maps.Map(document.getElementById("map_canvas"), this.options);
query = encodeURI('{site_url}{embed:map_url}');
var ctaLayer = new google.maps.KmlLayer(query,{
preserveViewport:true
});
ctaLayer.setMap(this.map);
}
}
$(document).ready(function() {
the_map.init();
the_map.load_map();
});
</script>
The Google Servers have an unspecified timeout, but testing shows it to be 3-5 seconds. This timeout is not something you can affect. The solution is to make your server respond faster. This issue almost always comes down to a file that is too big (yours isn't) or from dynamically generating the KML. You need to optimize this and that may mean finding a way to create a static KML file.
Features that are not clickable are almost certainly a problem with your KML. You can validate your KML to check for this:
Feed Validator
KML Validator
You can also test your KML by loading it at maps.google.com.

Resources