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/
Related
I am using Leaflet on my project. I work with PHP / Symfony, I retrieve the data from the Controller via fetch to display the markers on the map.
All markers are displayed on the map, but when using the markerCluster, markers that have close coordinates on the map (eg: same city) do not group together in clusters. The markers farther apart from each other group well together.
Have you an idea why ? Thanks
I am adding screens to you so that you can better understand :)
map.js
let iconPicture = L.icon({
iconUrl: "/assets/images/cycling.png",
iconSize: [20, 20],
popupAnchor: [0, -10],
});
function initMap() {
var map = L.map("mapId").setView([48.833, 2.333], 12);
var osmLayer = L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution: "© OpenStreetMap contributors",
minZoom: 3,
maxZoom: 19,
});
var markersGroup = L.markerClusterGroup({
disableClusteringAtZoom: 13,
spiderfyOnMaxZoom: false,
removeOutsideVisibleBounds: true,
});
fetch("/api/map")
.then((response) => {
return response.json();
})
.then((result) => {
result.forEach((element) => {
var cluster = L.marker([element.latitude, element.longitude], {
icon: iconPicture,
})
// Nous ajoutons la popup. A noter que son contenu peut être du HTMl
.bindPopup(
function (layer) {
return (
"<span>" +
element.name +
"</span>" +
"<br>" +
"<div class='img-hover-zoom'>" +
"<a href=" +
"/collection50_60/" +
element.id +
">" +
"<img class='picturePopup' src=/assets/images/uploads/" +
element.pictureFront +
">" +
"</a>" +
"</div>" +
"<br>" +
element.city +
"<br>" +
"<a href=" +
"/collection50_60" +
">" +
element.years +
"</a>"
);
},
{ className: "pop-up-leaflet", direction: "top" } //then add your options
)
.addTo(map);
markersGroup.addLayer(cluster);
});
map.addLayer(markersGroup);
})
.catch(() => console.error("error"));
}
window.onload = function () {
initMap();
};
That is just because you add your Markers (variable cluster) to both the map and the MarkerClusterGroup.
Simply add them only to MCG and let the latter handle everything.
var cluster = L.marker(latLng, options)
.bindPopup()
//.addTo(map); <= do not add your Marker directly to the map
markersGroup.addLayer(cluster); // <= let the MCG handle everything
The purpose of the map is when a user selects a HTML input it pulls a geojson file and places the zip code information on the map for that state. Then a second geojson file will pull the state bounds and also put it on the map and zoom to that state. Currently I am trying to accomplish this with two Geojson AJAX calls. One is called geojson and the other is statelay (see below). When I just have the map run with only the geojson object it runs fine and the interaction with the zip codes runs smoothly. However, when I add statelay the interactivity no longer works with the first geosjon call. Here is what the interactivity looks like when it works: https://www.freepropertycalc.com/maps.
Here are the specific questions:
-Why does adding the statelay object below interfere with the interactivity of the other geojson call?
-How can I simply get the bounds from statelay and make the map zoom to those state bounds?
Code:
<select id="select" >
<option value="">State </option>
<option value="{{url_for('static', filename= 'AK.js' )}}">AK</option>
<option value="{{url_for('static', filename= 'AL.js' )}}">AL</option>
<!-- a whole bunch more states -->
</select>
</div>
<div id="map2" class = "content-section middle toppad" ></div>
<script type="text/javascript">
var state = '/static/state.js';
var select = document.getElementById('select') ;
select.addEventListener('change', function(){
var ourRequest = new XMLHttpRequest();
var strUser = select.options[select.selectedIndex].text;
ourRequest.open('GET',select.value)
ourRequest.onload = function(){
document.getElementById('map2').innerHTML = "<div id='llmap'></div>";
var TILE_URL = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
var MB_ATTR = 'Map data © OpenStreetMap contributors';
map = L.map('llmap', {});
L.tileLayer(TILE_URL, {attribution: MB_ATTR}).addTo(map);
map.setView(new L.LatLng(38.500000, -98.000000), 4);
function onLocationError(e) {
alert(e.message);
}
// control that shows state info on hover
var info = L.control();
info.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info');
this.update();
return this._div;
};
info.update = function (props) {
this._div.innerHTML = '<h6>Market Info by ZIP Code</h6>' + (props ?
'<b>' + 'ZIP: ' + props.ZIP + '</b><br />' +
'Median Home Property Value, May 2020: ' + props.valmay2020 + '<br />' +
'Median Home Sale Price, March 2020: ' + props.salemarch2020 + '<br />' +
'Median Rent, April 2020: ' + props.rentapr2020 + ', City Level Only' + '<br / >' +
'1yr. House Value Change: ' + props.chg1yrpropval +'%' + '<br />'
: 'Hover over a ZIP Code');
};
info.addTo(map);
// get color depending on population density value
function getColor(d) {
return d > 400000 ? '#800026' :
d > 300000 ? '#BD0026' :
d > 200000 ? '#E31A1C' :
d > 150000 ? '#FC4E2A' :
d > 100000 ? '#FD8D3C' :
d > 50000 ? '#FEB24C' :
d > 25000 ? '#FED976' :
'#FFEDA0';
}
function style(feature) {
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.valmay2020)
};
}
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
info.update(layer.feature.properties);
}
var geojson;
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
function onEachFeature(feature, layer) {
layer.on({
click: highlightFeature,
mouseout: resetHighlight,
dbblick: zoomToFeature
});
}
var geojson = new L.GeoJSON.AJAX(select.value, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
var statelay = new L.GeoJSON.AJAX(state, {
filter: statefilter
}).addTo(map);
function statefilter(feature) {
if (feature.properties.STUSPS == strUser) return true
}
map.attributionControl.addAttribution('Housing and Rental data © Zillow');
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend'),
grades = [0, 25000, 50000, 100000, 150000, 200000, 300000, 400000],
labels = [],
from, to;
for (var i = 0; i < grades.length; i++) {
from = grades[i];
to = grades[i + 1];
froml = grades[i]/1000 + 'k';
tol = grades[i +1]/1000 + 'k';
labels.push(
'<i style="background:' + getColor(from + 1) + '"></i> ' +
froml + (to ? '–' + tol : '+'));
}
div.innerHTML = labels.join('<br>');
return div;
};
legend.addTo(map);
};
ourRequest.send();
});
This is a easy fix.
Your interactivity is gone, because you add the state geojson over the interactivity geojson. Two solutions:
call statelay.bringToBack() when you want to display the area / border
don't add it to the map, if you don't want to show it. Remove .addTo(map) from var statelay = new L.GeoJSON.AJAX(...).addTo(map)
Zoom to the bounds: Wait until the geojson is loaded and the call fitBounds
statelay.on('data:loaded', function() {
map.fitBounds(statelay.getBounds())
})
But you will have a problem with zooming to the bounds for example with AK, because the shape is not correct (But that can't fixed by me):
And this is very lazy because this is a very big file ... so I recommand you a other way to zoom to the area:
zoom to the bounds of the geojson layer, then it is zoomed directly after the interactiv shapes are loaded.
geojson.on('data:loaded', function() {
map.fitBounds(geojson.getBounds())
})
I am only attaching the script tag. Below is the flow of events that happen and the problem I see. I would appreciate any suggestions/advice.
I trigger the businessGeocoder by searching for an address, which triggers the businessAddress function inside the initialize function, which in turn triggers the businessLocationClickInfo function. This works perfectly.
Without refreshing the page I decide to use the employeeResidenceGeocoder by searching for an address, which triggers the employeeResidenceAddress function inside the initialize function, which in turn triggers the employeeResidenceLocationClickInfo function. This works perfectly. too.
Again, without refreshing the page I decide to use the businessGeocoder again by searching for an address, which triggers the businessAddress function inside the initialize function, which in turn SHOULD trigger the businessLocationClickInfo function, but instead, it triggers the employeeResidenceLocationClickInfo function. The employeeResidenceLocationClickInfo function, while it should have not been called, returns the correct data. I am having a hard time understanding why it is being called instead of the businessLocationClickInfo function.
Please note that doing it the other way, using employeeResidenceGeocoder first and then businessGeocoder, and then back to employeeResidenceGeocoder causes the same problem.
Update>> I ran console logs after each line and found out that because the click events are called in the initialize function, every time I click on the map both businessLocationClickInfo and employeeResidenceLocationClickInfo are being called, one replacing the other output div, whereas I want to only call one of them, depending on the geocoder. But I still haven't found a way/order to fix it.
<script>
var map;
var businessGeocoder;
var employeeResidenceGeocoder;
var businessLocationClickFeature;
var employeeResidenceLocationClickFeature;
var screenPoint;
var address;
var geocodeFeature;
var geocodePopup;
var geocodeCensusTract;
var geocodeCensusBlockGroup;
var businessLocationPolygon;
var employeeResidenceLocationPolygon;
function initialize() {
businessGeocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
flyTo: {
speed: 100
},
zoom: 17,
placeholder: "Search for a business location",
mapboxgl: mapboxgl
})
employeeResidenceGeocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
flyTo: {
speed: 100
},
zoom: 17,
placeholder: "Search for an employee's residence",
mapboxgl: mapboxgl
})
// // // adds geocoder outside of map (inside of map would make it a 'map control')
// document.getElementById('geocoder1').appendChild(businessGeocoder.onAdd(map));
// document.getElementById('geocoder2').appendChild(employeeResidenceGeocoder.onAdd(map));
map.addControl(businessGeocoder);
map.addControl(employeeResidenceGeocoder);
businessGeocoder.on('result', businessAddress);
employeeResidenceGeocoder.on('result', employeeResidenceAddress);
}
function businessAddress (obj) {
address = obj.result.place_name;
$(".geocode-result-area").html('<b>Geocoded Business Address: </b>' + address + '<br/><div class="medium-font">Click the blue address pin on the map for updated results.</div>');
$(".geocode-click-result-area").html("");
map.on('click', businessLocationClickInfo);
}
function employeeResidenceAddress (obj) {
address = obj.result.place_name;
$(".geocode-result-area").html('<b>Geocoded Employee Residence Address: </b>' + address + '<br/><div class="medium-font">Click the blue address pin on the map for updated results.</div>');
$(".geocode-click-result-area").html("");
map.on('click', employeeResidenceLocationClickInfo);
}
function businessLocationClickInfo (obj) {
businessLocationClickFeature = map.queryRenderedFeatures(obj.point, {
layers: ['tract-4332-1sbuyl','blockgroups-4332-9mehvk','businesslocation']
});
if (businessLocationClickFeature.length == 3) {
$(".geocode-click-result-area").html('<br/>This area meets the <span style="background-color:yellow">business location criteria</span> based on the following thresholds:'
+ '<table><tr><td>Renewal Community</td><td>' + businessLocationClickFeature[2].properties.Inquiry1 + '</td></tr>'
+ '<tr><td>CT & BG Poverty Rate ≥ 20%</td><td>' + businessLocationClickFeature[2].properties.Inquiry2 + '</td></tr></table>'
+ '<p><b>' + businessLocationClickFeature[0].properties.CountyName + " County" + '<br/>'
+ businessLocationClickFeature[0].properties.NAMELSAD + '<br/>'
+ businessLocationClickFeature[1].properties.NAMELSAD + '</b></p>'
+'<table><tr><th></th><th>Poverty Rate</th></tr><tr><td>CT '
+ businessLocationClickFeature[0].properties.TRACTCE + '</td><td>'
+ businessLocationClickFeature[0].properties.PovRate + "%" + '</td></tr><tr><td>BG '
+ businessLocationClickFeature[1].properties.BLKGRPCE + '</td><td>'
+ businessLocationClickFeature[1].properties.PovRate + "%" + '</td></tr></table>'
);
}
else {
$(".geocode-click-result-area").html('<br/> This area <u style = "color:red;">does not</u> meet the business location criteria based on the following thresholds:'
+ '<table><tr><td>Renewal Community</td><td>No</td></tr>'
+ '<tr><td>CT & BG Poverty Rate ≥ 20%</td><td>No</td></tr></table>'
+ '<p><b>' + businessLocationClickFeature[0].properties.CountyName + " County" + '<br/>'
+ businessLocationClickFeature[0].properties.NAMELSAD + '<br/>'
+ businessLocationClickFeature[1].properties.NAMELSAD + '</b></p>'
+ '<table><tr><th></th><th>Poverty Rate</th></tr><tr><td>CT '
+ businessLocationClickFeature[0].properties.TRACTCE + '</td><td>'
+ businessLocationClickFeature[0].properties.PovRate + "%" + '</td></tr><tr><td>BG '
+ businessLocationClickFeature[1].properties.BLKGRPCE + '</td><td>'
+ businessLocationClickFeature[1].properties.PovRate + "%" + '</td></tr></table>'
);
}
}
function employeeResidenceLocationClickInfo (obj) {
employeeResidenceLocationClickFeature = map.queryRenderedFeatures(obj.point, {
layers: ['tract-4332-1sbuyl','blockgroups-4332-9mehvk','employeeresidencelocation']
});
if (employeeResidenceLocationClickFeature.length == 3) {
$(".geocode-click-result-area").html('<br/>This area meets the <span style="background-color:yellow">employee residence location criteria</span> based on the following thresholds:'
+ '<table><tr><td>Renewal Community</td><td>' + employeeResidenceLocationClickFeature[2].properties.Inquiry1 + '</td></tr>'
+ '<tr><td>CT % LMI ≥ 70%</td><td>' + employeeResidenceLocationClickFeature[2].properties.Inquiry2 + '</td></tr>'
+ '<tr><td>CT & all BG Poverty Rate ≥ 20%</td><td>' + employeeResidenceLocationClickFeature[2].properties.Inquiry3 + '</td></tr></table>'
+ '<p><b>' + employeeResidenceLocationClickFeature[0].properties.CountyName + " County" + '<br/>'
+ employeeResidenceLocationClickFeature[0].properties.NAMELSAD + '<br/>'
+ employeeResidenceLocationClickFeature[1].properties.NAMELSAD + '</b></p>'
+ '<table id="CensusTable"><tr><th></th><th>Poverty Rate</th><th>LMI</th></tr><tr><td>CT '
+ employeeResidenceLocationClickFeature[0].properties.TRACTCE + '</td><td>'
+ employeeResidenceLocationClickFeature[0].properties.PovRate + "%" + '</td><td>'
+ employeeResidenceLocationClickFeature[0].properties.LMIPerc + "%" + '</td></tr>');
var BGsin20PovertyCT = map.queryRenderedFeatures(
{ layers: ['blockgroups-4332-9mehvk'],
filter: ["==", "TRACTCE", employeeResidenceLocationClickFeature[0].properties.TRACTCE]
});
var unique = [];
var distinct = [];
for (let i = 0; i < BGsin20PovertyCT.length; i++ ){
if (!unique[BGsin20PovertyCT[i].properties.BLKGRPCE]){
distinct.push(BGsin20PovertyCT[i]);
unique[BGsin20PovertyCT[i].properties.BLKGRPCE] = 1;
}
}
for (let i = 0; i < distinct.length; i++ ){
$("#CensusTable").append('<tr><td>BG ' + distinct[i].properties.BLKGRPCE + '</td><td>'
+ distinct[i].properties.PovRate + "%" + '</td><td>-</td></tr></table>'
);
}
}
else {
$(".geocode-click-result-area").html('<br/> This area <u style = "color:red;">does not</u> meet the employee residence location criteria based on the following thresholds:'
+ '<table><tr><td>Renewal Community</td><td>No</td></tr>'
+ '<tr><td>CT % LMI ≥ 70%</td><td>No</td></tr>'
+ '<tr><td>CT & all BG Poverty Rate ≥ 20%</td><td>No</td></tr></table>'
+ '<p><b>' + employeeResidenceLocationClickFeature[0].properties.CountyName + " County" + '<br/>'
+ employeeResidenceLocationClickFeature[0].properties.NAMELSAD + '<br/>'
+ employeeResidenceLocationClickFeature[1].properties.NAMELSAD + '</b></p>'
+ '<table id="CensusTable"><tr><th></th><th>Poverty Rate</th><th>LMI</th></tr><tr><td>CT '
+ employeeResidenceLocationClickFeature[0].properties.TRACTCE + '</td><td>'
+ employeeResidenceLocationClickFeature[0].properties.PovRate + "%" + '</td><td>'
+ employeeResidenceLocationClickFeature[0].properties.LMIPerc + "%" + '</td></tr>');
var BGsin20PovertyCT = map.queryRenderedFeatures(
{ layers: ['blockgroups-4332-9mehvk'],
filter: ["==", "TRACTCE", employeeResidenceLocationClickFeature[0].properties.TRACTCE]
});
var unique = [];
var distinct = [];
for (let i = 0; i < BGsin20PovertyCT.length; i++ ){
if (!unique[BGsin20PovertyCT[i].properties.BLKGRPCE]){
distinct.push(BGsin20PovertyCT[i]);
unique[BGsin20PovertyCT[i].properties.BLKGRPCE] = 1;
}
}
for (let i = 0; i < distinct.length; i++ ){
$("#CensusTable").append('<tr><td>BG ' + distinct[i].properties.BLKGRPCE + '</td><td>'
+ distinct[i].properties.PovRate + "%" + '</td><td>-</td></tr></table>'
);
}
}
}
mapboxgl.accessToken = 'pk.eyJ1Ijoia3l1bmdhaGxpbSIsImEiOiJjanJyejQyeHUyNGwzNGFuMzdzazh1M2k1In0.TcQEe2aebuQZ4G7d827A9Q';
map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/kyungahlim/ckd226uao1p7i1iqo8ag2ewmu',
center: [-95.925, 29.575],
zoom: 7
});
map.on('load', initialize);
// // Center the map on the coordinates of any clicked symbol from the 'symbols' layer.
// map.on('click', 'symbols', function(e) {
// map.flyTo({
// center: e.features[0].geometry.coordinates
// });
// });
// // Change the cursor to a pointer when the it enters a feature in the 'symbols' layer.
// map.on('mouseenter', 'symbols', function() {
// map.getCanvas().style.cursor = 'pointer';
// });
// // Change it back to a pointer when it leaves.
// map.on('mouseleave', 'symbols', function() {
// map.getCanvas().style.cursor = '';
// });
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-95.925, 29.575]
},
properties: {
title: 'Mapbox',
description: 'Washington, D.C.'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.414, 37.776]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}]
};
// // geocode the typed-in address, zoom to the location, and put a pin on address
// function codeAddress() {
// sAddress = document.getElementById('inputTextAddress').value;
// geocoder.geocode( { 'address': sAddress}, function(results, status) {
// //latitude = results[0].geometry.location.lat();
// //longitude = results[0].geometry.location.lng();
// coordinate = results[0].geometry.location;
// if (status == google.maps.GeocoderStatus.OK) {
// if (GeocodeMarker){
// GeocodeMarker.setMap(null);
// }
// // bounds.extend(results[0].geometry.location);
// // PuppyMap.fitBounds(bounds);
// PuppyMap.setCenter(results[0].geometry.location);
// PuppyMap.setZoom(14);
// GeocodeMarker = new google.maps.Marker({
// map:PuppyMap,
// position: results[0].geometry.location,
// animation: google.maps.Animation.DROP,
// icon: housePin,
// zoom: 0
// });
// }
// else{
// alert("Geocode was not successful for the following reason: " + status);
// }
// });
// }
var marker = new mapboxgl.Marker(document.createElement('div'))
.setLngLat( [-95.925, 29.575])
.addTo(map);
// // add markers to map
// geojson.features.forEach(function(marker) {
// // create a HTML element for each feature
// var el = document.createElement('div');
// el.className = 'marker';
// // make a marker for each feature and add to the map
// new mapboxgl.Marker(el)
// .setLngLat(marker.geometry.coordinates)
// .addTo(map);
// });
</script>
I have this code to add to Leaflet map marker genereted by JSON file
jQuery().ready(function (){
$.getJSON(
'/EUREKA/json/map_container/json_map_container.php',
function(data){
for ( var i=0; i < data.length; ++i )
{
k=i;
var myIcon = L.icon({
iconUrl: 'maps/images/' + data[i].type + '.png',
iconRetinaUrl: 'maps/images/' + data[i].type + '.png',
iconSize: [42, 55],
iconAnchor: [9, 21],
popupAnchor: [0, -14]
});
markerArray[i] = L.marker( [data[i].latitude, data[i].longitude], {id: data[i].id, icon: myIcon, draggable:'true'} )
.bindPopup( '<div>' + '<b>PDL di riferimento:</b> ' + data[i].codice + '<br/>'
+ '<b>Riferimento appaltatore:</b> '
+ data[i].companyId + '<br/>'
+ '<b>Tipo contenitore:</b> '
+ data[i].type + '<br/>'
+ '<b>Numero RDP:</b> '
+ data[i].rdpNumber + '<br/>'
+ '<b>Preposto di riferimento:</b> '
+ data[i].preposto + '<br/>'
+ '<b>Descrizione del rifiuto:</b> '
+ data[i].description
+ '</div>',
{direction: 'left'} )
.addTo( map );
//markerArray[i] = marker1;
markerArray[i].on('dblclick', function(e){
console.log("ID Marker Array: " + markerArray[k].options.id);
var latitudeMarker = markerArray[k].getLatLng().lat;
var longitudeMarker = markerArray[k].getLatLng().lng;
$.getJSON(
'/EUREKA/json/map_container/json_update_position.php?&lat=' + latitudeMarker + '&lng=' + longitudeMarker + '&id=' + markerArray[k].options.id,
function(data){
console.log("Posizione aggiornata")
});
});
}
});
The JSON 'json_map_container.php' file return date from a sql query. I want to update the position of a marker in the map when i drag it in a new position at the doubleclick event, I think to call a JSON 'json_update_position.php' with new position and id of marker and The JSON execute a UPDATE query on my db but when I doubleclick on marker I have ever the last id generated. Can anyone help me?
Read about closures in JavaScript, and have a look at example 5 in this excellent answer that describes your problem : basically, k will always be the last value set when read in your callback.
You could apply what's explained in this answer or get the reference to the marker in the event object passed to your callback by e.target:
markerArray[i].on('dblclick', function(e){
var marker = e.target;
console.log("ID Marker Array: " + marker.options.id);
var latitudeMarker = marker.getLatLng().lat;
var longitudeMarker = marker.getLatLng().lng;
$.getJSON(
'/EUREKA/json/map_container/json_update_position.php?&lat=' + latitudeMarker + '&lng=' + longitudeMarker + '&id=' + marker.options.id,
function(data){
console.log("Posizione aggiornata")
});
});
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";