change google maps custom icon with zoom - javascript

I am trying to change my google map markers so that when the zoom is < 5 they change from their custom markers to a star image.
This is what I have so far (not working)
//zoom icons to stars at continent level
google.maps.event.addListener(busMap, 'zoom_changed', function() {
var markerIconStar = google.maps.MarkerImage("icons/star.png");
var currentZoom = busMap.getZoom();
if (currentZoom < 5){
markerSanFran.setIcon(markerIconStar);
markerLA.setIcon(markerIconStar);
markerHollywood.setIcon(markerIconStar);
markerSantaCruz.setIcon(markerIconStar);
markerSanDiego.setIcon(markerIconStar);
markerLasVegas.setIcon(markerIconStar);
markerGrandCan.setIcon(markerIconStar);
markerMamLakes.setIcon(markerIconStar);
markerYosemite.setIcon(markerIconStar);
}
});
http://screamingeagle.travel/map/map2.html is a where you can see the rest of the code in action currently

You are adding your zoom_changed listener to the map before the busMap is defined, so it doesn't ever fire. Add it to busMap where that is defined (in your loadBusMap function)
function loadBusMap() {
//The empty map variable ('busMap') was created above. The line below creates the map, assigning it to this variable. The line below also loads the map into the div with the id 'bus-map' (see code within the 'body' tags below), and applies the 'busMapOptions' (above) to configure this map.
busMap = new google.maps.Map(document.getElementById("bus-map"), busMapOptions);
directionsDisplay = new google.maps.DirectionsRenderer();
//Assigning the two map styles defined above to the map.
busMap.mapTypes.set('map_styles_bus', styled_bus);
busMap.mapTypes.set('map_styles_bus_zoomed', styled_bus_zoomed);
//Setting the one of the styles to display as default as the map loads.
busMap.setMapTypeId('map_styles_bus');
//Calls the function below to load up all the map markers and pop-up boxes.
loadMapMarkers();
google.maps.event.addListener(busMap, 'zoom_changed', function() {
var markerIconStar = google.maps.MarkerImage("icons/star.png");
var currentZoom = busMap.getZoom();
if (currentZoom < 5){
markerSanFran.setIcon(markerIconStar);
markerLA.setIcon(markerIconStar);
markerHollywood.setIcon(markerIconStar);
markerSantaCruz.setIcon(markerIconStar);
markerSanDiego.setIcon(markerIconStar);
markerLasVegas.setIcon(markerIconStar);
markerGrandCan.setIcon(markerIconStar);
markerMamLakes.setIcon(markerIconStar);
markerYosemite.setIcon(markerIconStar);
}
});
}

Related

Leaflet.js: zoom map to visible markers

I have a leaflet.js map with a collection of markers, which can be shown/hidden in a legend div done with plugin Leaflet.StyledLayerControl (I think this is not too relevant but just in case).
I can capture the event when layers are shown or hidden and in that event I would like to zoom to fit all visible markers.
There are a few questions in SO with a very similar title but most of them pretend to fit zoom to a known collection of markers, which is not my case (some other questions with very similar subject refer to Google maps, not leaflet).
So, the question would be:
A) Can I set zoom to fit all visible markers?
B) or, how can I get an array of all visible markers to apply the other solutions seen?
This is how I create markers on map:
const icon_general = L.divIcon({html: '<i class="fas fa-map-marker fa-2x"></i>', iconSize: [20, 20], className: 'node_icon'});
var node_10031 = L.marker([40.7174605,-3.9199218],{ icon: icon_general}).addTo(layer1);
node_10031.bindPopup('<h2>Title</h2>');
var node_10032 = L.marker([40.7184576,-3.9202692],{ icon: icon_general}).addTo(layer1);
node_10032.bindPopup('<h2>Title</h2>');
var node_10032 = L.marker([40.7361371,-3.9453966],{ icon: icon_general}).addTo(layer2);
node_10032.bindPopup('<h2>Title</h2>');
Layers are then hidden or shown and I can capture that event, that is where I want to modifiy zoom or loop through visible markers.
EDIT (final solution based on Seth Lutske response):
This is my final solution, maybe it's less eficient as on each click it loops through all visible markers in map, but after some attempts this was the succesful one (I wasn't able to manage properly the individual events for add/remove layer):
function setZoom2Visible()
{
var visibleLayerGroup = new L.FeatureGroup();
mymap.eachLayer(function(layer){
if (layer instanceof L.Marker)
visibleLayerGroup.addLayer(layer);
});
const bounds = visibleLayerGroup.getBounds();
mymap.fitBounds(bounds);
}
$('.menu-item-checkbox input[type=checkbox]').click(function(){
setZoom2Visible();
});
Create a featureGroup and add the markers to it:
const myGroup = L.featureGroup([node_10031, node_10032, node_10033]);
On whatever event you're using to capture the markers being added to the map, you can get the bounds of the featureGroup and set the map's bounds to that:
function onMarkersAddedEventHandler(){
const bounds = myGroup.getBounds();
map.fitBounds(bounds);
}
Now if you're saying that each marker has its own toggle in the UI, it's a bit more complicated. You'll have to attach an event to each marker's UI checkbox, and on change of that checkbox, add or remove the marker from the group, then reset the bounds:
const node_10031_checkbox = document.querySelector('input[type="checkbox"]#10031');
function onMarkersAddedEventHandler(e){
if (e.target.checked){
myGroup.addLayer(node_10031)
} else {
myGroup.removeLayer(node_10031)
}
const bounds = myGroup.getBounds();
map.fitBounds(bounds);
}

Preserving Google map zoom to kml layer on checkbox click

I'm attempting to add multiple kml layers to a map that can be turned on and off with check boxes. I got that part working (yay!). When I click on a layer to turn it on, it zooms in (this is fine), but when I unclick to turn the layer off, it zooms back out to my map extent. How do I get it to preserve the zoom of the last loaded layer? Code below.
<script>
var map;
var watershedLayer = new google.maps.KmlLayer ({
url: 'http://mvihes.bc.ca/mapping/watersheds.kmz'
});
var ere1949Layer = new google.maps.KmlLayer ({
url: 'http://mvihes.bc.ca/mapping/ere1949.kmz'
});
function initialize() {
var parksville= new google.maps.LatLng(49.316786, -124.308768);
var mapOptions = {
zoom: 9,
center: parksville
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
check();
}
function check()
{
if(document.getElementById('watersheds').checked)
{watershedLayer.setMap(map);}
else
{watershedLayer.setMap(null);}
if(document.getElementById('ere1949').checked)
{ere1949Layer.setMap(map);}
else
{ere1949Layer.setMap(null);}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I tried using the preserveViewport function but it just stopped the layer from zooming in, which is not what I wanted. I'm new to javaScript so possibly I'm missing something obvious...any help would be appreciated!
jsfiddle
Set the map-property of a selected layer only when it's not set yet:
function check()
{
if(document.getElementById('watersheds').checked)
{if(!watershedLayer.getMap())watershedLayer.setMap(map);}
else
{watershedLayer.setMap(null);}
if(document.getElementById('ere1949').checked)
{if(!ere1949Layer.getMap())ere1949Layer.setMap(map);}
else
{ere1949Layer.setMap(null);}
}
http://jsfiddle.net/jhagmq7L/16/
You can also attach max and min zoom levels to the map, something to consider the over all map zoom when loading kml layers.
// sets the min and max zoom levels of the map
var opt = { minZoom: 6, maxZoom: 18 };
map.setOptions(opt);

Can not use same function for two listeners

I am trying to create two maps, with two Markers (one marker on each map).
On dragging the marker, its position is updated in the DIV element in the page. And on moving the map, the marker is moved to the center of the map and the DIV element is again updated.
I have created functions to make the respective changes. To identify which marker or map is to be checked or moved, I pass the map or marker variable in the function.
However, the map showing weird behavior. On trying to drag a marker, it gets attached to my mouse pointer and is never dropped on the map and no event is triggered.
Also, moving the map does not do anything.
If I declare the function separately for each marker or map in the form
addListener(marker, 'drag', function() { //some code });
it works perfectly fine.
Not sure what is going wrong.
Here is the code snippet:
//add a listener for the marker movement
google.maps.event.addListener(marker_start, 'drag', handleMarkerDrag(marker_start, 1));
google.maps.event.addListener(marker_end, 'drag', handleMarkerDrag(marker_end, 2));
//add a listener for the map
google.maps.event.addListener(map_start, 'dragend', handleMapDragend(map_start, marker_start, 1));
google.maps.event.addListener(map_end, 'dragend', handleMapDragend(map_end, marker_end, 2));
and the functions which handle the events:
function handleMarkerDrag(marker, x)
{
//get the current location of the marker
var marker_pos = marker.getPosition();
//convert lat-lang datastructure into individual latitude and longitude
var lat = marker_pos.lat();
var lng = marker_pos.lng();
//now update the content in the html page
if(x == 1)
{
document.getElementById("longitude_start").innerHTML = lng+'<input type="hidden" name="longitude_start" value='+lng+'>';
document.getElementById("latitude_start").innerHTML = lat+'<input type="hidden" name="latitude_start" value='+lat+'>';
}
else
{
document.getElementById("longitude_end").innerHTML = lng+'<input type="hidden" name="longitude_end" value='+lng+'>';
document.getElementById("latitude_end").innerHTML = lat+'<input type="hidden" name="latitude_end" value='+lat+'>';
}
}
function handleMapDragend(map, marker, x)
{
//get the current location of the marker
var marker_pos = map.getCenter();
//set marker to the enter of the map
marker.setPosition(marker_pos);
//convert lat-lang datastructure into individual latitude and longitude
var lat = marker_pos.lat();
var lng = marker_pos.lng();
//now update the content in the html page
if(x == 1)
{
document.getElementById("longitude_start").innerHTML = lng+'<input type="hidden" name="longitude_start" value='+lng+'>';
document.getElementById("latitude_start").innerHTML = lat+'<input type="hidden" name="latitude_start" value='+lat+'>';
}
else
{
document.getElementById("longitude_end").innerHTML = lng+'<input type="hidden" name="longitude_end" value='+lng+'>';
document.getElementById("latitude_end").innerHTML = lat+'<input type="hidden" name="latitude_end" value='+lat+'>';
}
}
If I declare the function separately for each marker or map in the form it works perfectly fine. Not sure what is going wrong.
The difference is that the first attempt provides a function as argument, but the other attempt(that fails) is a function-call(which will be executed immediately).
Wrap the function-call into an anonymous function:
//add a listener for the marker movement
google.maps.event.addListener(marker_start, 'drag', function(){handleMarkerDrag(marker_start, 1);});
google.maps.event.addListener(marker_end, 'drag', function(){handleMarkerDrag(marker_end, 2);});
//add a listener for the map
google.maps.event.addListener(map_start, 'dragend', function(){handleMapDragend(map_start, marker_start, 1);});
google.maps.event.addListener(map_end, 'dragend', function(){handleMapDragend(map_end, marker_end, 2);});

Take screenshot of google map [duplicate]

I'm working on functionality to take snapshot of google map with polylines and open popup window on polyline click on google map.
The snapshot of google map with polylines is working
but it will not able to take snapshot open popup window on polyline.
polyline are showing on sanpshot picture but info window are not showing .
Here is code to take snapshot.
This code is to initialize the code control on javascript onload :
var snapShotControlOptions = { hidden: true };
snapShotControlOptions.buttonLabelHtml="<snap id='snap' style='display:none' >snap</span>"
snapShotControl = new SnapShotControl(snapShotControlOptions);
map.addControl(snapShotControl);
here is the method take snap to take the sanp shot of google map .
function takeSnap() {
//static map size
var sizeStr = "640x640";
var imgSize = "";
if (sizeStr != "") {
var sizeArray = sizeStr.split("x");
imgSize = new GSize(sizeArray[0], sizeArray[1]);
}
snapShotControl.setMapSize(imgSize);
var format = "jpg";
snapShotControl.setFormat(format);
var url = snapShotControl.getImage();
// document.getElementById("snapshot_canvas").src = url;
SaveImage(url);
//
}
//this will add polyline overlay to draw line on google map with different color of polyline on google map .
var polyline = directionsArray[num].getPolyline();
polyline.setStrokeStyle({ color: streetColor, weight: 3, opacity: 0.7 });
polyline.ssColor=streetColor;
map.addOverlay(polyline);
///this code will open the pop info window on polyline those polyline created on google map
and problem is their these pop window not included on sanpshot when i take sanpshot of google map.
var MousePoint = "";
var marker;
GEvent.addListener(map, "mousemove", function (point) {
MousePoint = new GLatLng(point.lat(), point.lng());
});
GEvent.addListener(polyline, "click", function () {
map.openInfoWindowHtml(MousePoint, headMarkerHtml);
});
GEvent.addListener(polyline, "mouseout", function () {
// map.closeInfoWindow();
});
can you please tell who i pass popup window in polyline overlay .
i have use javascript file snapshotcontrol.js to take the snapshot.
from the snapshotcontrol source
This library makes it easy to generate an image "snapshot" of your
interactive map, using the Google Static Maps API.
Static maps doesn't support info windows or anything like adding custom text to the map
https://developers.google.com/maps/documentation/staticmaps/index
You could draw the map on a canvas within the browser then
draw the info window on top of that using this http://html2canvas.hertzen.com/
and then download the canvas content

How to get some information in google maps without click event on marker and show this in a div, other than infoWindow

Hi I am showing some markers on my google map and on click of the marker, I am calling the click event and showing some info about that place to the right side(area other than Map and not as an infoWindow). Now this event gets fired on click, and by default when page loads my div remains blank, How can I have the div the basic information being shown up once the map loads up. I need to show the information that corresponds to the marker that is the center point of the map, and later when the users click the marker icons the info should change and correspond to the particular marker being clicked
I have tried something but it doesn't work:
function loadMap() {
var myLatlng = new google.maps.LatLng(40.46998, -3.68705);
var myOptions = {
zoom: 3,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), myOptions);
var places = [];
places.push(new google.maps.LatLng(51.43581, -0.51744));
places.push(new google.maps.LatLng(48.87187, 2.31764));
places.push(new google.maps.LatLng(45.45979, 9.19681));
var infowindow;
for(var i = 0; i<places.length; i++) {
var marker= new google.maps.Marker({
position: places[i],
map: map,
title: 'Place' + i
});
(function (i,marker){
google.maps.event.addListener(marker, 'click' , function() {
infowindow.setContent('PLace Number' + i)
infowindow.open(i, marker)
});
});(i, marker);
}
}
$("document").ready(function () {
loadMap();
});
UPDATE EDITED
Basically I need something like Layer KML features
But the info should come on the right hand side by default for the first time. Later on when the marker is clicked, the info should change. I am also not adamant that I need this info in a kml file(xml is fine with me as well). I can just have a marker and info should popup on click and for the first time be default as well depending on the location of the user.
Bottom Line: I need the info to appear on click of a marker and by default when the page loads the info should appear corresponding to the center point of the map. which means users coming from different locations will see different info's corresponding to their location from where they are coming.(I am centering the map based on users location)
You can use the addDomListener event of the google maps api. Something like this:
<script>
function initialize() {
// Map initialization
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<body>
<div id="map_canvas"></div>
</body>
Although the above code is Maps Javascript API code, the addDomListener() method binds to the window object of the browser and allows the API to communicate with objects outside of the API's normal domain.
further reading
Actually the basic Idea is that you need to read an XMl and parse the data and and show this in a seperate div on right side., This div you can create dynamically when you load the map e-g:
$("#body").append("<div class='newdiv'></div>")
From the google Docs in the section about InfoWindow:
Note that if you call open() without passing a marker, the InfoWindow
will use the position specified upon construction through the
InfoWindow options object.
So in your code, why don't you simply init your infoWindow and call the open() method? I am not particularly familiar with the api, but how about:
var infowindow = new google.maps.InfoWindow({
content: 'your initial text'
});
infowindow.open();
Or if you need the marker for special purposes on the infowindow, init an marker with the center position and use that in the infowindow.open(your_initial_pos) call.
You can use jQuery to .triger() a click event on the first marker on document.ready:
$(marker).trigger('click');
This will run the code you have already written and make it so when the page loads your div will be populated with data from whatever element you trigger the click on.
When you bind to document.ready you don't need encapsulate document in quotes:
$(document).ready(function () {...});
Or you could use the short-hand if you're into that sort of thing:
$(function () {...});
UPDATE
You can place the trigger function call after your for loop where you are setting up the markers:
for(var i = 0; i<places.length; i++) {
var marker= new google.maps.Marker({
position: places[i],
map: map,
title: 'Place' + i
});
(function (i,marker){
google.maps.event.addListener(marker, 'click' , function() {
infowindow.setContent('PLace Number' + i)
infowindow.open(i, marker)
});
});(i, marker);
//only run on the first marker
if (i === 0) {
//trigger a click event to show the first info-window
$(marker).trigger('click');
}
}
You can fire a tilesloaded event on the map object. Check out the Map reference for events
tilesloaded waits until the map tiles are actually loaded before firing. Using your code, you could do something like this:
function loadMap() {
var myLatlng = new google.maps.LatLng(40.46998, -3.68705);
var myOptions = {
zoom: 3,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), myOptions);
google.maps.event.addListener(map, 'tilesloaded', function() {
doSomething();
});

Categories