I am trying to toggle a button which will hide/show the google marker placed in the map. I have been searching for an answer on SOF but all offered array method. I am wondering if it is possible to do it without array.
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat: 1.3420894594991328, lng: 103.83490918886719},
});
var ntuc = {
lat: 1.32805676,
lng: 103.9216584
};
var ntucmap = new google.maps.Marker({
position: ntuc,
map: map,
icon: 'https://maps.google.com/mapfiles/kml/paddle/blu-stars.png'
});
}
function toggleNTUCmap() {
if (!ntucmap.getVisible()) {
ntucmap.setVisible(true);
} else {
ntucmap.setVisible(false);
}
}
Button
<button class="button-oj pure-button" onclick="toggleNTUCmap()">
<i class="fas fa-hospital"></i> NTUC</button>
For function toggleNTUCmap(), I have tried the following which still won't work.
ntucmap.setMap(ntucmap.getMap() ? null : map);
Can't you do something like this?
function clearMap(map) {
for(var i = 0; i<ntucmap.length; i++){
ntucmap[i].setMap(null);
}
}
and for the show part
function setMapOnAll(map) {
for (var i = 0; i < ntucmap.length; i++) {
ntucmap[i].setMap(map);
}
}
Then to have it in one button you can keep a counter with your button and when it's even do one function when it's odd do the other?
// Adds a marker at the center of the map.
var ntuc = {lat: 1.32805676, lng: 103.9216584};
addMarker(ntuc);
setMapOnAll(null);
// Adds a marker to the map and push to the array.
function addMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map,
icon: 'https://maps.google.com/mapfiles/kml/paddle/blu-stars.png'
});
markers.push(marker);
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
// Show/Hide Markers
var counter = 0;
function toggleMarkers() {
if (counter == 0) {
setMapOnAll(map);
counter = 1;
} else {
setMapOnAll(null);
counter = 0;
}
}
In the end, I used array to save all the markers. Based on the button which user used to toggle, it will determine whether it marker(s) will be shown on the map or not.
Related
This is the updated final code that I got it to work. I use the get.zoom and center.change to ensure that no matter the view of the map, there will always be 10 markers on the map! (original question below
'''
// Declare map and markers array globally
var map, markers = [];
function initMap() {
var myLatLng = {
lat: 0,
lng: 0
};
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: myLatLng,
zoomControl: true
});
// Moved this out of the AJAX success and declared variable correctly
var infowindow = new google.maps.InfoWindow();
// Listen for zoom change event
// Handle markers display
google.maps.event.addListener(map, 'zoom_changed', handleMarkersDisplay);
$.ajax({
type: 'GET',
url: 'https://us-central1-cloud-calendar-project.cloudfunctions.net/InfoWindow',
success: function(data) {
data = JSON.parse(data);
for (var element in data) {
var marker = new google.maps.Marker({
position: {
lat: data[element].lat,
lng: data[element].lon
},
map: map,
title: element,
visible: false, // Default visibility is false
marker_celsius: data[element].celsius // Add celsius as marker property
});
console.log("marker#" + marker.getPosition().toUrlValue());
// Push this marker to the markers array
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker, element) {
return function() {
var content = 'Country: ' + data[element].country;
content += '<br>Temperature (°C): ' + data[element].celsius;
content += '<br>Day: ' + data[element].day;
content += '<br>Month: ' + data[element].month;
infowindow.setContent(content);
infowindow.open(map, marker);
}
})(marker, element));
}
// All markers have been added, sort the markers array by celsius value
markers.sort(function(a, b) {
return b.marker_celsius - a.marker_celsius;
});
map.addListener('center_changed', function() {
window.setTimeout(handleMarkersDisplay() , 3000);
});
// Handle markers display
handleMarkersDisplay();
}
});
}
function handleMarkersDisplay() {
console.log("handleMarkerDisplay zoom=" + map.getZoom());
// Check if map current zoom <= 2
if (map.getZoom() <= 2) {
hideAllMarkers();
displayMarkers();
} else if (map.getZoom() == 3) {
hideAllMarkers();
displayMarkers();
} else if (map.getZoom() == 4) {
hideAllMarkers();
displayMarkers();
} else if (map.getZoom() == 5) {
hideAllMarkers();
displayMarkers();
}
}
function hideAllMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setVisible(false);
}
}
function displayMarkers() {
// add new markers to map
var shownMarkers = 10;
for (var i = 0; i < markers.length; i++) {
// Only show the first 10 markers in the viewport
if (shownMarkers > 0) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
shownMarkers--;
}
} else {
markers[i].setVisible(false);
}
}
}
function displayAllMarkers() {
// Zoom is greater than 3, show all markers
for (var i = 0; i < markers.length; i++) {
markers[i].setVisible(true);
}
}
'''
I am working on a web application whereby I want to show markers on a map based on the highest temperature recorded (from a JSON file I parse through). Currently, I am able to get the 10 highest temperatures markers on the map but when I zoom in it does not get updated to add new markers. So when I zoom in one I go from 10 markers to 8 markers in view(you need to scroll to see the other two markers). I would like to add two new markers that correspond to the next highest markers for that view so that whatever view/zoom you have you always see 10 markers! (probably not possible at some level, eg only see one country). The picture below demonstrates that at zoom 3, two markers are left out of view.
I found this implementation (https://github.com/endiliey/cs50/blob/master/pset8/mashup/static/scripts.js) by endiliey. However the implementation is not working..
If you want to show the highest 10 markers in the viewport, you need to count those:
function displayMarkers() {
// add new markers to map
var shownMarkers = 10;
for (var i = 0; i < markers.length; i++) {
// Only show the first 10 markers in the viewport
if (shownMarkers > 0) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
shownMarkers--;
} else {
markers[i].setVisible(false);
}
} else {
markers[i].setVisible(false);
}
}
}
Then call that function, when you load new markers or update the zoom:
proof of concept fiddle
code snippet:
// Declare map and markers array globally
var map, markers = [];
function initMap() {
var myLatLng = {
lat: 0,
lng: 0
};
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: myLatLng,
zoomControl: true
});
// Moved this out of the AJAX success and declared variable correctly
var infowindow = new google.maps.InfoWindow();
// Listen for zoom change event
// Handle markers display
google.maps.event.addListener(map, 'zoom_changed', handleMarkersDisplay);
$.ajax({
type: 'GET',
url: 'https://us-central1-cloud-calendar-project.cloudfunctions.net/InfoWindow',
success: function(data) {
removeMarkers();
data = JSON.parse(data);
for (var element in data) {
var marker = new google.maps.Marker({
position: {
lat: data[element].lat,
lng: data[element].lon
},
map: map,
title: element,
visible: false, // Default visibility is false
marker_celsius: data[element].celsius // Add celsius as marker property
});
console.log("marker#" + marker.getPosition().toUrlValue());
// Push this marker to the markers array
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker, element) {
return function() {
var content = 'Country: ' + data[element].country;
content += '<br>Temperature (°C): ' + data[element].celsius;
content += '<br>Day: ' + data[element].day;
content += '<br>Month: ' + data[element].month;
infowindow.setContent(content);
infowindow.open(map, marker);
}
})(marker, element));
}
// All markers have been added, sort the markers array by celsius value
markers.sort(function(a, b) {
return b.marker_celsius - a.marker_celsius;
});
console.log("loaded "+markers.length+" markers");
// Handle markers display
handleMarkersDisplay();
}
});
}
function handleMarkersDisplay() {
console.log("handleMarkerDisplay zoom=" + map.getZoom());
// Check if map current zoom <= 2
if (map.getZoom() <= 5) {
displayMarkers();
} else {
displayAllMarkers();
}
}
function removeMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
}
function hideAllMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setVisible(false);
}
}
function displayMarkers() {
// add new markers to map
var shownMarkers = 10;
for (var i = 0; i < markers.length; i++) {
// Only show the first 10 markers in the viewport
if (shownMarkers > 0) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
shownMarkers--;
} else {
markers[i].setVisible(false);
}
} else {
markers[i].setVisible(false);
}
}
}
function displayAllMarkers() {
// Zoom is greater than 3, show all markers
for (var i = 0; i < markers.length; i++) {
markers[i].setVisible(true);
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap" async defer></script>
I have included google map for the project that I'm working with. I have few checkboxes which are dynamic and when click on a checkbox according to that those locations will be displayed on google map. As follows: The thing is it is not refreshing and remove the previous markers when I check or uncheck those checkboxes again and again.
Vue Component:
<div v-for="vnos in vehicle_nos">
<input class="" type="checkbox" name="vehicle_num" :value="vnos.name" v-model="vehicle_nums" #change="getVehicleNumbers(vehicle_nums)">
<label for="vehicle_num">{{vnos.name}}</label><br>
</div>
functions I trigger:
getVehicleNumbers(vehicle_num){
this.allSelectedVehicles = vehicle_num;
axios.post('gps/get-gps-location/'+this.allSelectedVehicles)
.then(response => {
for (let i = 0; i < response.data.data.length; i++) {
this.all_data = JSON.parse(response.data.data[i]);
this.longtitudes = this.all_data.item.pos.x;
this.latitudes = this.all_data.item.pos.y;
let longlatitude = this.latitudes+','+this.longtitudes;
this.geocoder = new google.maps.Geocoder;
this.infowindow = new google.maps.InfoWindow;
//here I pass those coordinates to geocodeLatLng() function
this.geocodeLatLng(this.geocoder, this.map, this.infowindow, longlatitude);
}
}).catch(Erors => {
console.log('errors');
});
},
geocodeLatLng(geocoder, map, infowindow, longlatitude = null) {
var input = longlatitude;
var latlngStr = input.split(',', 2);
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
//latlng looks like '6.916333,79.861018' this
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
map.setZoom(11);
var marker = new google.maps.Marker({
position: latlng,
map: map,
});
infowindow.setContent(results[0].formatted_address);
infowindow.open(map, marker);
} else {
// alert('No results found');
}
} else {
// alert('Geocoder failed due to: ' + status);
}
});
},
In my controller I pass the data as an array to the response in axios.post('gps/get-gps-location/'+this.allSelectedVehicles) this one.
Then I loop all those and set markers one by one. But what I need is to remove all markers from the google map and display the upcoming response data. It's not removing and shows the upcoming markers as well as existing markers also. So there are few markers on same point.
I tried most of the given examples and links on stackoverfow also but couldn't able to find a better solution. Your help is appreciated a lot.
Finally changed the previous code and can be used it as follows
getVehicleNumbers(vehicle_num){
this.loading = false;
if (vehicle_num.length == 0) {
this.allSelectedVehicles = 0;
} else {
this.allSelectedVehicles = vehicle_num;
}
axios.post('gps/get-gps-location/'+this.allSelectedVehicles)
.then(response => {
this.deleteMarkers();
for (let i = 0; i < response.data.data.length; i++) {
this.all_data = JSON.parse(response.data.data[i]);
this.longtitudes = this.all_data.item.pos.x;
this.latitudes = this.all_data.item.pos.y;
let longlatitude = {lat: this.latitudes, lng: this.longtitudes};
this.addMarker(longlatitude);
this.loading = true;
}
}).catch(Erors => {
this.loading = true;
});
},
addMarker(location) {
let marker = new google.maps.Marker({
position: location,
map: this.map,
});
this.markersArray.push(marker);
},
setMapOnAll(map) {
for (var i = 0; i < this.markersArray.length; i++) {
this.markersArray[i].setMap(map);
}
},
clearMarkers() {
this.setMapOnAll(null);
},
deleteMarkers() {
this.clearMarkers();
this.markersArray = [];
},
Once check the checkbox then it'll trigger getVehicleNumbers function. and through that the markers will be shown in the map. And if the checkbox is unchecked again the function will trigger and reset the map. then it'll show the new markers only.
I have a map where initially the markers load coming from the database, Then i have a time based Ajax request which gets the records again after every 1 minute.
Following is the code where i am using setMapOnAll(null) as from the Google maps Documentation, But its not working.
success: function(data){
var positions = [];
$.each(data.riders, function(index, value) {
positions.push({
lat: value.rider_location.lat,
lng: value.rider_location.lng,
content: value.name,
id : value.id
});
});
map.setCenter({
lat: parseInt(positions[0].lat),
lng: parseInt(positions[0].lng)
});
var infowindow = new google.maps.InfoWindow();
var marker,
i;
setMapOnAll(null); //Remove the existing markers
while(positions.length){
positions.pop().setMap(null);
}
for (i = 0; i < positions.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(positions[i].lat,positions[i].lng),
map: map,
id : positions[i].id,
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
}
}) (marker, i));
}
}
How can i remove the existing markers before adding new ones.
there is method marker.setMap(null) as google docs https://developers.google.com/maps/documentation/javascript/markers
you need create array of markers then remove all from map in loop by call method marker.setMap(null)
var markers = [];
for (i = 0; i < positions.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(positions[i].lat,positions[i].lng),
map: map,
id : positions[i].id,
});
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
}
}) (marker, i));
}
You should add this function to your code and call it where you add new markers then add new markers. This will delete the previous markers.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
I am creating a google maps page. I am dynamically adding markers through a loop. I want to display when I click on any marker. How can I achieve that? This is my loop.
if(data.STATUS == STATUS.SUCCESS){
console.log("Markers Received");
deleteMarkers();
for(var i=0; i<data.DATA.length; i++){
addMarker({lat: data.DATA[i].LATITUDE, lng: data.DATA[i].LONGITUDE},data.DATA[i].INCIDENT);
}
}
function deleteMarkers() {
clearMarkers();
markers = [];
}
function addMarker(location,incident) {
var marker = new google.maps.Marker({
position: location,
map: map,
title: incident
});
markers.push(marker);
}
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
function deleteMarkers() {
clearMarkers();
markers = [];
}
function clearMarkers() {
setMapOnAll(null);
}
function showMarkers() {
setMapOnAll(map);
}
First of all I delete all the markers by this function. And then reset them. This call runs after every minute. I want to display the incident when ever I click on the marker. How can I achieve that?
Hope, this helps.
var obj = {
infoWindow: new google.maps.InfoWindow(),
marker: new google.maps.Marker({
map: map,
position: latLngObj,
title: 'info name'
})
};
google.maps.event.addListener(obj.marker, 'click', function() {
obj.infoWindow.setContent("<div><b>" + obj.marker.title + "(" + distance + ")</b></div>");
obj.infoWindow.open(map, obj.marker);
});
I'm trying to get the markers longitude and latitude and display them on the map but I'm not getting any result, my parser.php file is working and fetching the data from the database i just need to format it into javascript anyone ?
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: { lat: -25.363882, lng: 131.044922},
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
$.getJSON('parser.php', function(items) {
for (var i = 0; i < items.length; i++) {
(function(item) {
addMarker(item.lat, item.lon);
})(items[i]);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
parser.php output
[{"0":"33.880561","lat":"33.880561","1":"35.542831","lon":"35.542831"},{"0":"-25.363882","lat":"131.044922","1":"35.513477","lon":"35.513477"}]
addMarker needs to take map as an argument.
function addMarker(map, lat, long) {
var latlong = google.maps.LatLng(lat, long);
return new google.maps.Marker({
position: latlong,
map: map
});
}
Then your loop should be:
for (var i = 0; i < items.length; i++) {
item = items[i];
addMarker(map, item.lat, item.lon);
}
You don't need to put the addMarker calls into a closure, because these aren't separate callbacks.