Good Day to all I just wanna ask something about Leaflet Markers.
I have a database and a table with a field that has a name of icon_name and it looks like this.
|icon_name|
___________
|FIRE |
|HOMICIDE |
|RAINSTORM|
and I also have a folder Named Legends and it has a file that looks like this.
Folder Name: Legends
Files Inside:
FIRE.jpg
HOMICIDE.jpg
RAINSTORM.jpg
as you can see the names of jpg files is the same in my table (icon_name)
My code below is calling a specific image in a folder and uses this as a Leaflet markers image before placing it in the map (Note: The following code is generating the markers info from database into the map)
var Icon1 = L.icon({ //<---Assigning a name of an image into a Leaflet Icon.
iconUrl: 'legends/FIRE.jpg',//<--- Image Folder Location + the Image Name
iconSize: [50, 50], //<--- Size of the image converted as icon
iconAnchor: [23, 50], //<--- Icons Anchor
popupAnchor: [3, -50] //<--- Leaflet Pop up
function getInfo() {
$.getJSON("get_info.php", function (data) {
for (var i = 0; i < data.length; i++) {
var location = new L.LatLng(data[i].lat, data[i].lng);
var marker = new L.Marker(location,{icon:Icon1});
marker.bindPopup(
data[i].name + "<br>" +
data[i].user_date + "<br>" +
data[i].user_time + "<br>" +
data[i].address + "<br>"
).addTo(map);
marker.on('click', function(e) { // HERE YOU GO
var ll = marker.getLatLng();
document.querySelector('#userLat1').value = ll.lat;
document.querySelector('#userLng1').value = ll.lng;
alert('You have selected a Marker that will be deleted');
});
}
});
}
Now the output of the code above is like this:
A lot of markers from different parts of the map (good)
All of that markers image is only "FIRE.jpg" even if the other markers has an "icon_name" of HOMICIDE,RAINSTORM and others.
Now here is my big question: How can I pass the value of my tables field icon_name into the value of var Icon1 or iconUrl
var Icon1 = L.icon({
iconUrl: 'legends/FIRE.jpg',
so that the output will be different markers with different markers image. I hope you understand me. TY
Based on the given answer on me this is my tested code but its not working.
(Part of the code)
for (var i = 0; i < data.length; i++) {
var location = new L.LatLng(data[i].lat, data[i].lng);
var Icon1 = L.icon({
iconUrl: 'legends/FIRE.jpg',
marker.bindPopup(
data[i].name + "<br>" +
data[i].user_date + "<br>" +
data[i].user_time + "<br>" +
data[i].address + "<br>"
).addTo(map);
Im not sure where you're setting the IconURL, but something along the lines of this should do it.
var marker = data[i].marker;
var url = "legends/" + marker + ".jpg";
Related
I'm making website where I bring information about multiple events using XHR (Ajax) call. Every event has information like name, address and city. I'm listing all these events using innerHTML. Every event has button "show on map" which puts marker to that event's address and shows it on the google map. My problem is that every time I press "show on map" button on any event, it puts marker of the last event's address into a map. I can't figure out right way to make it work so it uses right address and not always the last one. I currently have 10 events (since info.length is 10) but all 10 buttons make the marker in the same place. All help is appreciated!
Here's how I do it:
function bringInfo() {
var info = JSON.parse(req.responseText);
for (var i = 0; i < info.length; i++) {
header = info[i].title;
description = info[i].description;
address = info[i].contact_info.address;
city = info[i].contact_info.city;
link = info[i].contact_info.link;
pic = info[i].image.src;
makeEvent(header,description,address,city,link,pic);
}
}
Function where I make event with InnerHTML:
function makeEvent(header, description, address, city, link, pic) {
var newDiv = document.createElement('div');
var containerElem = document.getElementById('container');
var eventHTML = "<div class = 'panel'> <h1 id ='header'>" + header + "</h1>" +
"<img src = '" + pic + "'>" +
"<p>" + description + "</p>" +
"<p>Address:" + address +"</p>" +
"<p>City:" + city +"</p>" +
"<p>Link: <a href ='" + link + "'>" + link + "</a></p>" +
"<button onclick ='geocodeAddress(address)'>Show on map" + "</button>";
newDiv.innerHTML = eventHTML;
newDiv.className += "panel";
containerElem.appendChild(newDiv);
}
EDIT:
var myMap;
function geocodeAddress(address) {
var coder = new google.maps.Geocoder();
coder.geocode({'address': address}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
myMap.setCenter(results[0].geometry.location);
putMarker (results[0].geometry.location, address);
} else {
alert('Geocoding didnt work. Reason: ' + status);
}
});
}
function putMarker(p, text) {
var ownMarker =
new google.maps.Marker({
position: p,
map: myMap,
title: text
});
}
function initMap() {
myMap = new google.maps.Map(document.getElementById('map'), {
center: {lat: 33.33, lng: 33.33},
zoom: 15
});
}
I think you should change this part:
"<button onclick ='geocodeAddress(address)'>Show on map" + "</button>"
to
"<button onclick ='geocodeAddress(\"' + address + '\")'>Show on map" + "</button>"
Currently your onclick event calls geocodeAddress() function with value of the global variable address. The global variable address contains the value for last element in your for loop.
I am having an issue with Google Maps cluster function. It is correctly clustering and placing cluster counts on the map and the cumulative counts total the correct number of locations/markers given it. But no icons are showing when the count of the locations within a given cluster is greater than 9 (or greater than 1 digit count). Does anyone have an idea how to correct this? I am using the "standard" Google Maps blue icons for the clusters. The blue icon shows for a cluster of 4 markers. But the clusters of 132 and 79 markers only display the 132 and 79 counts -- no blue icons. I don't have a convenient place to quickly put a screen capture for public consumption.
var tableContent = "";
$.each(data, function (i, item) {
iCount++;
var aCount = iCount.toString();
var iCt = item.RECNO;
//table += "<tr><td>" + '(' + aCount + ') ' + item.DDSPNM + "</td></tr>";
tableContent += '<tr>';
var rowContent = "";
rowContent += "<strong>" + item.DDSPNM + "</strong>" + "<br>"
rowContent += item.DCTRNUM;
tableContent += '<td>' + rowContent + '</td>';
tableContent += '</tr>';
var latlng = new google.maps.LatLng(item.Latitude, item.Longitude);
locations.push(latlng);
var marker = new google.maps.Marker({
position: latlng,
label: { text: aCount, color: 'black', fontSize: "12px" },
title: 'this is ' + item.DDSPNM,
map: map
});
gmarkers.push(marker);
});
if (iCount == 0)
{
table += "<tr><td>No providers were found in the specified location. Please change your search criteria and try the search again.</td></tr>";
tableContent += "<tr><td>No providers were found in the specified location. Please change your search criteria and try the search again.</td></tr>";
}
$('#results').append(tableContent);
// Instantiate pagination after data is available
pager = new Pager('results', 10);
pager.init();
pager.showPageNav('pager', 'pageNavPosition');
pager.showPage(1);
// set the bounds for the map and re-size/re-position to display all markers
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < locations.length; i++) {
bounds.extend(locations[i]);
}
map.fitBounds(bounds);
var markerCluster = new MarkerClusterer(map, gmarkers,
{ imagePath: #Url.Content("~/Images/m")});
}
Please ignore what is ugly presentation for the user, that's the piece I am working on now. But I'm stumped as to why icons for clusters don't show when the count is greater than 9 (or greater than 1 digit).
Sorry for clogging up the works with this question. All I can say is duh...I thought all of the icons were enabled in my VS project and that is wrong. All I can say is that once I enabled all icons the yellows, reds, etc. starting appearing with multiple digit counts.
Sorry for personal screw up!
So I've set up this simple map:
var map = L.mapbox.map('map', 'mapbox.streets')
.setView([52.15, 5.5], 8);
var myLayer = L.mapbox.featureLayer().addTo(map);
// Add custom popups to each using our custom feature properties
myLayer.on('layeradd', function(e) {
var marker = e.layer,
feature = marker.feature;
// (stuff happens)
marker.bindPopup(popupContent,{
closeButton: false,
minWidth: 500
});
});
// the following is where it all goes wrong:
// Run easings when links are clicked
var side = document.getElementById('map-ui');
for (var i = 0; i < features.length; i++) { // for all the number of features we have
var a = side.appendChild(document.createElement('a')); // add a 'a' child to the side element
a.onclick = (function(feature, i) { // when you click on it
return function() {
map.setView( [ // centre the map to the appropriate coordinates
feature.geometry.coordinates[1],
feature.geometry.coordinates[0]+0.03 // +0.03 puts it a bit to the left, to make room for the tooltip
],12);
Here is where I want to open the popup but I'm not sure how to trigger the right marker to open up. For the real life example, visit www.boerenmetwater.nl. The following four examples don't work:
//marker()[1].openPopup();
//map.marker[i].openPopup();
//t.openPopup(this);
//marker.openPopup();
}
}
)
(features[i], i);
a.href = '#';
a.title = 'klik om naar ' + features[i].properties.plaats + ' te gaan';
a.innerHTML = '<div class = "menu_plaatsnaam">' + features[i].properties.plaats + '</div>';
a.innerHTML += '<div class = "menu_titel">' + features[i].properties.titel + '</div>';
}
I am working on a "Colorado Offroad Trails" webmap for fun and am stuck on an issue. I am very green to Leaflet but have managed to get most of what I want done. My next step is to change my markers based on the trail rating... basically green for easy yellow for medium and red for hard. I created a JSFIDDLE with map. You might have to go tothe trailroute.js or the trailhead.js to make the markers display (hosted on a http site)
So in short i want to change the marker color based on the feature.properties.High_Ratin attribute.
JSFIDDLE: https://jsfiddle.net/GratefulFisherman/Lftnr036/
Code:
// Mapbox Access Token
L.mapbox.accessToken = 'pk.eyJ1IjoibWF0dHJ1c3NvIiwiYSI6IjVlYzk3OTEzOTczZTEwYTMyNDRjZDA4NDY1MjYzNWNmIn0.0wkKxVGJyO8nEKjn2GcV3A';
// Create the map
var map = L.mapbox.map('map', null, {
minZoom: 7
}).setView([39.117, -105.353], 7);
// Setup basemaps for layer list
var baseMaps = {
Streets: L.mapbox.tileLayer('mapbox.streets'),
Outdoors: L.mapbox.tileLayer('mapbox.outdoors'),
Satellite: L.mapbox.tileLayer('mapbox.satellite'),
};
// Add Streets to the map
baseMaps.Streets.addTo(map);
// Trailhead popup
function onEachFeaturetrailhead(feature, layer) {
if (feature.properties && feature.properties.Trail) {
layer.bindPopup("<h2>" + feature.properties.Trail + '<br></h2>'
+ "<li>Low Rating | " + feature.properties.Low_Rating + '<br></li>'
+ "<li>High Rating | " + feature.properties.High_Ratin + '<br></li>'
+ "<li>Trail Damage | " + 'Link<br></li>'
+ "<li>Latitude | " + feature.properties.Latitude + '<br></li>'
+ "<li>Longitude | " + feature.properties.Longitude + '<br></li>'
+ "<li>Close to | " + feature.properties.Location + '<br></li>'
+ "<li>County | " + feature.properties.County + '<br></li>'
+ "<li>Land Owner | " + feature.properties.Land_Owner + "</li>");
}
}
// Trail Tracks Popup
function onEachFeaturetrailtrack(feature, layer) {
if (feature.properties && feature.properties.Trail) {
layer.bindPopup("<b>" + feature.properties.Trail + "</b>");
}
}
// Add the popup to the GeoJSON layer
var geoJsonLayer = L.geoJson(geoJSONtrailhead, {
onEachFeature: onEachFeaturetrailhead
});
// Create new Marker Clusters
var markers = new L.MarkerClusterGroup();
// Add Markers to map
markers.addLayer(geoJsonLayer);
map.addLayer(markers);
// Add Markers to Layer Control
var layerControl = {
"Trail Heads": markers
};
// Add the basemap toggle button with the basemaps in the list
L.control.layers(baseMaps, layerControl).addTo(map);
// GPS Track
var lineStyle = {
"color": "#F4A460",
"weight": 4,
"opactiy": 0
};
// Trail Route Popup
var tracks = L.geoJson(geoJSONtrailtrack, {
onEachFeature: onEachFeaturetrailtrack,
style: lineStyle
});
// Set Scale dependency to a layer
map.on('zoomend', function(e) {
if ( map.getZoom() <= 10 ){ map.removeLayer( tracks )}
else if ( map.getZoom() > 10 ){ map.addLayer( tracks ) }
});
I honestly have been tooling around looking for a solution but cant find anything. Like i said I am green to this so any help would be appreciated.
You can get colored versions of Leaflet's default icon from leaflet-color-markers. You can define L.Icon objects for the various difficulty ratings using those images:
var redIcon = new L.Icon({
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
var yellowIcon = new L.Icon({
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-yellow.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
var greenIcon = new L.Icon({
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-green.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
(This is simply copying the example code from the color markers site, but you would probably want to change those URLs to point to your own hosted versions of those markers.)
To change the markers of each trailhead depending on the rating, you will want to use the setIcon method within your onEachFeature function and create a function that returns different icons based on the rating:
function onEachFeaturetrailhead(feature, layer) {
if (feature.properties && feature.properties.Trail) {
layer.bindPopup("<h2>" + feature.properties.Trail + '<br></h2>'
+ "<li>Low Rating | " + feature.properties.Low_Rating + '<br></li>'
+ "<li>High Rating | " + feature.properties.High_Ratin + '<br></li>'
+ "<li>Trail Damage | " + 'Link<br></li>'
+ "<li>Latitude | " + feature.properties.Latitude + '<br></li>'
+ "<li>Longitude | " + feature.properties.Longitude + '<br></li>'
+ "<li>Close to | " + feature.properties.Location + '<br></li>'
+ "<li>County | " + feature.properties.County + '<br></li>'
+ "<li>Land Owner | " + feature.properties.Land_Owner + "</li>");
layer.setIcon(getIcon(feature.properties.High_Ratin));
}
}
//get icons based on difficulty rating
function getIcon(rating) {
return rating > 6 ? redIcon :
rating > 3 ? yellowIcon :
greenIcon;
}
Here is an updated fiddle with these changes:
http://jsfiddle.net/nathansnider/p585s265/
I'm using the google places JavaScript API to get place details.
I am encountering two issues to do with JavaScript:
The first is extracting user reviews from the place.reviews array
I can get the place.name, place.phone, and place.formatted_address values but I am unable to retrieve the reviews from the place.reviews array.
I found some sample code on the link below to loop through the reviews array but I can't get it to work. I get script errors for example with the keyword forEach.
Google Places JS API Show Reviews
Is there an easy way to retrieve the values from the reviews array?
These are the script declarations at the top of my HTML document:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=places"></script>
<script>
The Second
I am creating a simple search app so I can view what's around me. I would like to add the distance and time from the start location to the venue the user clicks on i.e. 'London Bridge = 1 km, 10 mins'.
I can get the time and distance values using the Google matrix distance API using a callback function but I don't know how then to pass the values to the main part of my code.
I have had a look at some answers on here but I am still confused about how callback functions work:
function createMarkers(results, PlaceSearchStatus) {
var resultcontent = ''; //stores place results to be displayed on map
var resultdiv = document.getElementById('searchresults');
if (PlaceSearchStatus == google.maps.places.PlacesServiceStatus.OK) {
// if we have found something - clear map (overlays)
clearOverlays();
// and create new markers by search result
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
//use the Distance Matrix API to get the distance between this venue and start location
/distancematrix#distance_matrix_responses
var DistanceService = new google.maps.DistanceMatrixService();
var origin1 = new google.maps.LatLng(document.getElementById('lat').value, document.getElementById('lng').value);
var destination1 = results[i].geometry.location;
DistanceService.getDistanceMatrix({
origins: [origin1],
destinations: [destination1],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
function callback(response, DistanceMatrixStatus) {
if (DistanceMatrixStatus != google.maps.DistanceMatrixStatus.OK) {
alert('Distance matrix API Error was: ' + DistanceMatrixStatus);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
//getting the distance value gives more accurate results than the text value but not using that
//alert(results[i].distance.value + ", " + results[i].duration.value);
//get the time and distance to this location from our start location
// Need to fix. this isn't working as this is inside a callback function.
var TimeAndDistance = results[i].distance.text + ", " + results[i].duration.text;
}
}
} // end of distance matrix code
//concatonate the accessible search results and add on the time and distance to the place name
resultcontent += '<p> <h2>' + '<div <input id=\"button2\" type=\"button\" class=\"button\" value=\"' + results[i].place_id + '\" onclick=\"GetIndividualPlaceDetails(this);\">' + results[i].name + '</div> </h2>';
Thanks,
Tom
The following code works for accessing the reviews and I'm using another work around for my second question:
len = place.reviews.length;
for (i=0; i<len; ++i) {
resultcontent += place.reviews[i].rating + ' stars';
resultcontent += ', On ' + place.reviews[i].time + ' ' + place.reviews[i].author_name + ' said:';
if (!!place.reviews[i].text) resultcontent += '<br />' + place.reviews[i].text;
}
}