I have converted multiple shapefiles to KML using the Shp2kml2 software from Zonums Solutions. I have made a map with the KML layers (of which I have imported to google docs to get the url). As an example:
var ctaLayer = new google.maps.KmlLayer({
url: 'https://docs.google.com/uc?authuser=0&id=0B15UI5xGYTOadDlta2FoZ2pCc1E&export=download'
});
ctaLayer.setMap(map);
When I click on a polygon layer in google maps, the pop-up box opens. How can I make it so that when I click on a second polygon layer, the pop-up box that was selected earlier is automatically cleared and not shown anymore? (Because in my situation, the earlier pop-up box still shows up but I don't want this to happen because if the user selects multiple polygon layers, there would be too many pop-up box on the screen. I understand that the user can select X to delete the pop-up window but I would like to make it as user-friendly as possible).
In addition to the polygon layers, I have other point layers in the map. But when I try to click on a specific point, the pop-up information is that of the polygon which rests in the same place as the points.
My map is found in: http://userpages.flemingc.on.ca/~catam/collab.html
You could consider the following approach:
1)suppress a default info window:
var kmlOptions = {
suppressInfoWindows: true, // do not to display an info window when clicked
preserveViewport: false,
map: map
};
var layer = new google.maps.KmlLayer(url, kmlOptions);
2)register a shared instance of Info Window:
var infoWindow = new google.maps.InfoWindow();
var openInfoWindow = function (KMLevent) {
infoWindow.close();
infoWindow.setOptions(
{
content: KMLevent.featureData.infoWindowHtml,
position: KMLevent.latLng,
pixelOffset: KMLevent.pixelOffset
});
infoWindow.open(map);
};
google.maps.event.addListener(layer, "click", openInfoWindow);
Example
Related
I've been trying to solve this question for a week, and haven't found any solution yet.
All I found is marker that is placed by one's own can be changed.
My situation is I import a KML file with some marker,and I want to change the icon on click event.
The code below works fine
var ctaLayer = new google.maps.KmlLayer({
//KMZ KML
url: url,
map: map,
suppressInfoWindows: true,
});
ctaLayer.addListener('click', function (kmlEvent) {
var text = kmlEvent.featureData.description;
showInContentWindow(text); }
My Current Result
Most People use the below function to set different icon
marker.seticon(ICON)
But in my case I can't get the marker I click
Hope someone can help me!!
With KmlLayer you can't change the style after load (with the API as currently documented). One option would be to use a third party KML parser (like geoxml3 or geoxml_v3) which converts KML into native google maps api objects, which you can change.
geoxml3:
https://github.com/geocodezip/geoxml3
geoxml_v3:
http://code.google.com/p/geoxml-v3/
According to geocodezip's advice
I came out with this solution
var marker;
google.maps.event.addListener(ctaLayer, 'click', function (event) {
var eLatLng = event.latLng;
if (marker != null) //this will remove the previous marker
{
marker.setMap(null);
}
marker = new google.maps.Marker({
position: eLatLng,
map: map,
});
marker.setPosition((eLatLng));
marker.setIcon(ICON);
});
While clicking the kmlLayer marker,I overlay a new bigger marker on it.
I know it's not the best solution, but at least it tells users which marker they are now clicking.
Google Maps doesn't provide a way to break apart multiple markers that are at the same location. This can occur with a people or businesses at a multiple residency location such as an apartment building or professional services building. Depending at zoom level it can also occur at shopping malls, etc.
The way around that is to "spiderfy" them: when clicking on the first it breaks them out with a line to the location. This is done in Google Earth and George MacKerron wrote a package to do that for Google Maps. (https://github.com/jawj/OverlappingMarkerSpiderfier)
It can be integrated with markerclusterer, although it doesn't support marker clusterer's batch creation of markers.
My issue is that the application I'm working on wants to have specific icons for different types of activities. Spiderfier puts one of the markers on top. A person looking at the map has no way of knowing that there can be 10 or more other markers underneath the top marker.
Ideally, there would be a way to put a top marker that displays when there are multiple markers similar to the different icon in markercluster. It isn't a direct 1-to-1 since spiderfier also works when they are close but not exactly at the same location (default is 20 pixels) and markercluster has no provision for accessing multiple markers at the exact same location.
The ideal behavior would be have a special icon for spiders that broke into the spiderfied individual icons when clicked. Similar to markerclusterer, but without the zoom change and handling the same location. The special icon ideally would indicate how many other markers are at the spot, again like markerclusterer. The special icon could be hidden or become part of the spiderfied group.
Without some accommodation users would have no way of knowing multiple activities are at the location. They may even assume that the activity they want is not at that location because another activities marker is shown.
This is a plunker that has the problem: http://plnkr.co/edit/vimZNq?p=info
var markers = [];
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < 100; ++i) {
var latLng = new google.maps.LatLng(Math.floor(Math.random() * 10) / 10 + 39,
Math.floor(Math.random() * 10) / 10 - 100);
var marker = new google.maps.Marker({
position: latLng,
title: "marker " + i + " pos: " + latLng,
maxZoom: 8,
map: map
});
marker.desc = marker.getTitle();
bounds.extend(latLng);
markers.push(marker);
oms.addMarker(marker);
}
map.fitBounds(bounds);
var markerCluster = new MarkerClusterer(map, markers);
Thanks for your help,
David
Here's how I got it to work. Where map is a Gmap instance and oms is an Overlapping Marker Spiderfier instance. We're also using Marker Clusterer on the initial zoom which buys us a break.
map.addListener('zoom_changed', function() {
map.addListenerOnce('idle', function() {
// change spiderable markers to plus sign markers
// we are lucky here in that initial map is completely clustered
// for there is no init listener in oms :(
// so we swap on the first zoom/idle
// and subsequently any other zoom/idle
var spidered = oms.markersNearAnyOtherMarker();
for (var i = 0; i < spidered.length; i ++) {
// this was set when we created the markers
url = spidered[i].icon.url;
// code to manipulate your spidered icon url
};
});
});
oms.addListener('unspiderfy', function(markers) {
var spidered = markers;
for (var i = 0; i < spidered.length; i ++) {
url = spidered[i].icon.url;
// change it back
};
});
oms.addListener('click', function(marker) {
// put the clicked-on marker on top
// when oms un-spiders
marker.zIndex=999;
// set infowindow, panning etc.
});
I managed to match the following Versions:
MarkerClusterer 2.0.13
OverlappingMarkerSpiderfier 3.27
On every creation of a new Marker, i store the initialIconUrl in the Marker Object
var marker = new google.maps.Marker({
position: //some position
});
marker.setIcon(iconUrl);
marker.initialIconUrl = iconUrl;
When declaring the OverlappingMarkerSpiderfier, set the nearbyDistance to 0.001 (or some other very small value).
this.oms = new OverlappingMarkerSpiderfier(this.map, {
markersWontMove: true,
markersWontHide: true,
nearbyDistance: 0.001 //This will only spiderfy the Markers if they have the exact same position
});
Then, we need a listener on the maps 'idle' Event, to format the Markers manually.
I needed this because my SPIDERFIABLE Marker wouldn't show correctly on the first step, when transferring from the Clustered Marker to the seperate Markers.
var me = this;
google.maps.event.addListener(this.map, 'idle', function () {
me.oms.formatMarkers();
});
Listen to the oms 'format' Event and set the iconURL for Markers that are SPIDERFIABLE.
If the Marker is not spiderfiable, reset the Icon to the initial Url.
var spiderfiableIconUrl = //Whatever you need
this.oms.addListener('format', function (marker, status) {
var iconURL = status == OverlappingMarkerSpiderfier.markerStatus.SPIDERFIABLE
? spiderfiableIconUrl :
marker.initialIconUrl;
marker.setIcon(iconURL);
});
Hope this helps.
Some methods seems to be interesting like markersNearAnyOtherMarker but I cannot get it work.
An interesting way could be to use spiderfy and unspiderfy events and change marker when it's fired
overlappingMarkers = new OverlappingMarkerSpiderfier(map, overlapOptions);
overlappingMarkers.addListener('spiderfy', function (markers) {
markers.forEach(function (marker) {
marker.setLabel('*');
marker.setIcon(myNormalIcon);
})
})
overlappingMarkers.addListener('unspiderfy', function (markers) {
markers.forEach(function (marker) {
marker.setLabel(''+markers.length);
marker.setIcon(myOverlapIcon);
})
})
Unfortunatly, the unspiderfy event isn't fired until we open then close the overlap marker. If I find a conclusion to this solution I will update this post.
I have the following problem:
I'm working in an aplication to book hotels that has tabs ("Hotel Details", "Map", "Reviews") in the overview page. the tabs are created with angularjs.
also, in the page I have the hotel address that is a link to the "Map" tab.
When I click on the "Map" tab, the google map is rendering ok. But, when I click on the hotel address, the "Map" tab opens but the map is not centered. If I refresh the page, it appears centered.
this is the code that process the map:
$scope.loadMap = function (targetID){
var latitude = $scope.latitude;
var longitude = $scope.longitude;
if(latitude && longitude && document.getElementById(targetID) != null ){
var center = new google.maps.LatLng(latitude, longitude);
var map_options = {
zoom: 13,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(targetID), map_options);
// configure marker
var marker_options = {
map: map,
position: center,
title: $scope.hotelName
};
// create marker
var marker = new google.maps.Marker(marker_options);
var infoWindow = new google.maps.InfoWindow();
window.setTimeout(function(){
google.maps.event.trigger(map, 'resize');
},2000);
}
}
Can you help me, please?
I've had this very problem when I was creating maps using Leaflet.js. I was trying to initialize the map inside of my angular service and it was loading very strangely. It appears you are trying to do the same thing, but you're doing it inside of your controller, rather than a service, but the effect is the same thing.
The problem is timing. Your controller is run before the DOM finishes loading and before angular has a chance to scan through the DOM to build out your Map page partial. Because of that, the page is only partially loaded when you call $scope.loadMap, which loads the google map, as you would expect. The problem is that once Angular finishes scanning the DOM partial, it modifies the DOM and then loads it into the view. When this happens, the google map has already been initialized to its default size based on the previous state of the DOM, and doesn't resize properly when angular is finished with the DOM.
Ok, that was a long explanation, but here's how you fix it:
You should do all of your map initialization inside of a directive's linking function. You could create a directive called something like app.directive('hotelMap'), which would initialize your map using the $scope.latitude and $scope.longitude variables from your controller.
link: function(scope, elem, attrs){
var center = new google.maps.LatLng(scope.latitude, scope.longitude);
var map_options = {
zoom: 13,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(targetID), map_options);
// configure marker
var marker_options = {
map: map,
position: center,
title: $scope.hotelName
};
// create marker
var marker = new google.maps.Marker(marker_options);
var infoWindow = new google.maps.InfoWindow();
}
And then in your map partial, you would have an element that looks something like <div hotel-map></div>. This fixes your problem, because your map will never be initialized until Angular has finished scanning/modifying the DOM and has finished rendering your partial. That way, the map's containing element will be at its final size/position and the map will be loaded into the element's center properly. Give it a try and let me know if that works.
I have Google Map created with version of Google Maps api v3. It's "standard" Google Map, filled with markers and clusters. Every marker and cluster have it's own InfoWindow, showed when end user click on it.
What I need is that when map is loaded, to open all of InfoWindows of all markers and clusters showed on map.
Right now, they are showed only when I click on them:
google.maps.event.addListener(markerGreenCluster, 'clusterclick', function(markerGreenCluster) {
var content = '';
var info = new google.maps.MVCObject;
info.set('position', markerGreenCluster.center_);
var infowindow = new google.maps.InfoWindow();
aIWgreen.push(infowindow);
var center = markerGreenCluster.getCenter();
var size = markerGreenCluster.getSize();
var markers = markerGreenCluster.getMarkers();
// more code goes here...
})
I noticed that problem is in cluster definition, and method markerGreenCluster.getSize(); It returns number of grupped markers, and it can return it after whole map is loaded, or something like that.
Can you help me how can I achieve that all of InfoWindows are open (showed) when map is loaded?
the infowindows only open on click because you're only creating them on the click event listener. Move the code creating the infowindows out of the click handler, into a window load event handler instead.
To do this, what I do is create a InfoWindows object and stored it into the marker. Something like this
function CreateMarker(Lat, Lng, Title, Content) {
var aInfoWin = new google.maps.InfoWindow({
content: Content,
position: new google.maps.LatLng(Lat,Lng)
});
var aMarker = new StyledMarker({
title: Title,
position: new google.maps.LatLng(Lat,Lng),
MyInfoWin: aInfoWin
});
aMarker.MyInfoWin.open();
}
You can access to the Marker InfoWindows where you like (events, code,.....) like the other properties.
Code non tested, only to get the idea
Regards
Can you design a google map, with multiple locations, and when you click on a location it opens a link to that locations page?
The basic Google Maps page can be set up using instructions here.
Add markers in the initialize() function, using
var marker new google.mapsMarker({
position: new google.maps.LatLng(39.952517,-75.19618), //your coordinates
map: map,
title:"Location 1",
url: "http://www.location1.com",
});`
Then add links to the markers by adding an event listener to your map:
google.maps.event.addListener(marker, 'click', function() {
window.location.href = marker.url;
});
Here's a jsfiddle with a couple of markers. Keep in mind that the links won't open on jsfiddle but would open on a normal website.