I have a leaflet map, i added a point layer to it that returns from ajax call, i want to fit the map a little bit away from its bounds so that i can see the country it lies in it,how can this be done?
$.ajax({
type:"POST",
url:"CustomerID_geojson.php",
data:"OrdersID="+ Cust ,
dataType: 'json',
success: function (response)
{
geojsonLayer = L.geoJson(
response,
{
pointToLayer: function(feature, latlng)
{
var redMarker = L.AwesomeMarkers.icon({
icon: 'user',
markerColor: 'purple',
prefix: 'fa',
iconColor: 'white'
});
return L.marker(latlng, {icon:redMarker});
},
onEachFeature: function (feature, layer)
{
layer.bindTooltip('<label class="CustToolTip">Customer: ' + feature.properties.nick_name_) + '</label>';
}
}).addTo(mymap);
mymap.fitBounds(geojsonLayer.getBounds());
}
})
Cannot be done. A point is infinitesimally small and has zero area, so the bounding box of one point feature has zero area. Zooming to the maximum zoom level is the expected behaviour in this case.
You might want to use an alternative approach. e.g. create a L.Circle with the center in the marker, giving it a radius in meters, add it to the map so you can get its bounds, remove it from the map, then zoom to those bounds.
Related
I am trying to style individual markers, or clusters of size 1, based on some feature property.
var markers = L.markerClusterGroup();
function onEachFeature(feature, layer) {
if (feature.properties.EncounterType && feature.properties.Year) {
layer.bindPopup(feature.properties.EncounterType + " in " +
feature.properties.Year);
}
}
function style(feature) {
switch (feature.properties.EncounterType) {
case 'Shooting':
return {
color: "ff0000"
};
case 'Sighting':
return {
color: "0000ff"
};
case 'Hunting':
return {
color: "ff0000"
};
}
}
var geoJsonLayer = L.geoJSON(storer, {
onEachFeature: onEachFeature
}, {
style: style
});
markers.addLayer(geoJsonLayer);
map.addLayer(markers);
The onEachFeature function successfully creates the popups. However, the style function does not change the color of the clusters of size 1. I've tried using the iconCreateFunction when initializing the markerclustergroup, however, that did not work either.
Your style option is separated in a 3rd argument of your call to L.geoJSON factory, whereas it should have been placed within the 2nd argument, alongside onEachFeature option.
var geoJsonLayer = L.geoJSON(storer, {
onEachFeature: onEachFeature,
style: style
});
But that is probably not the only reason for your issue.
style option will apply to vector shapes (polylines, polygons, etc.), i.e. to non-point data. It may also apply to Circle Markers, which can be used for Point type geometries, but you have to explicitly create them (typically through the pointToLayer option).
Those non-point data cannot be handled by Leaflet.markercluster.
Therefore if you see "clusters of size 1" (I guess you mean markers), they come from unstyled Point type geometries in your storer GeoJSON data.
This is a normal marker:
It is a PNG image that cannot be styled.
If you want to customize the appearance of your Point geometries, use custom icons, a plugin that provide such custom icons, or Circle Markers which you can modify the colour easily (including through the style option).
For example, if you were to choose that last option, you could do something like:
var geoJsonLayer = L.geoJSON(storer, {
pointToLayer: function (geoJsonPoint, latlng) {
return L.circleMarker(latlng);
},
onEachFeature: onEachFeature,
style: style
});
I have a feature in a Leaflet map made up of many circle markers (L.circleMarker). The markers are symbolized to show whether a picture was taken at that location.
What I would like to do is bring all the markers that do have a photo at that location to the top of the layer, similar to how a marker can be raised with a mouse-over (but without mouse-over in this case).
Here is an illustration of the original version:
And this is what I would like them to be:
I've considered having different layers for photos vs. no photos, but due to some functions in the map, it's preferable that they are in a single layer.
Any ideas as to how this could be done with JavaScript and Leaflet?
In the style definition for the circle marker it's possible to specify the "map pane" to which the marker is rendered (http://leafletjs.com/reference-1.0.3.html#map-pane). It seems like this is the only way to specify the zIndex of circleMarkers (regular markers have a zindexOffset option).
My code looks like this:
var style = {
radius: 1.75,
fillColor: "darkred",
color: "darkred",
pane: 'overlayPane'
};
var picStyle = {
radius: 0.25,
fillColor: "blue",
color: "blue",
pane: 'shadowPane'
};
var site2 = new L.geoJSON(valuesSite2, {
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
feature.properties.layer = "Site 2";
onEachFeature: onEachFeature;
if (<there is a picture>) {
return L.circleMarker(latlng, picStyle)
} else {
return L.circleMarker(latlng, style);
}
}
}).addTo(map);
The result looks like:
I'm adding some points to a map using the code below and they look great. I'm also adding some json polygons without issue.
When a certain zoom level is reached I would like the points and polygons to turn off. Using the map.removeLayer(name of polygon) turns off the polygon perfectly and then zoom back out I use map.addLayer(name of polygon) and they come back (using 'zoomend' and if else statement).
The point features do not react to the removeLayer function like the polygons do. I've also tried to harvestPoints.setOpacity(0) which does not work either. What code should I use to turn these geojson markers "on" and "off" like the polygon features?
function onEachPoint(feature, layer) {
layer.bindPopup(feature.properties.MGNT_AREA.toString());
layer.on('click', function (e) { layer.openPopup(); });
layer.bindLabel(feature.properties.MGNT_AREA.toString(), {
noHide: true,
className: "my-label",
offset: [-2, -25]
}).addTo(map);
};
var areaIcon = {
icon: L.icon({
iconUrl: 'labels/MonitoringIcon.png',
iconAnchor: [20, 24]
})
};
var harvestPoints = new L.GeoJSON.AJAX('labels/dfo_areas_point.json', {
onEachFeature: onEachPoint,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, areaIcon);
}
});
Not sure exactly what is the root cause for your issue, as we are missing how exactly you reference yours points (markers) when you try to remove them from the map.
Normally, there should be no difference between polygons and points (markers) to achieve what you described (removing the layers from the map at certain zoom level, and add them back at other zooms).
Note that setOpacity is a method for L.Markers, whereas you apply it to harvestPoints which is your geoJson layer group.
What may happen is that you add individual points (markers) to your map (last instruction in your onEachPoint function), but try to remove the layer group harvestPoints from map. Because it seems to be never added to the map, nothing happens.
If you want to turn on/off ALL the points in your harvestPoints layer group at the same time, then you would simply add / remove that layer group to / from the map, instead of adding individual markers:
var harvestPoints = L.geoJson.ajax('labels/dfo_areas_point.json', {
onEachFeature: onEachPoint,
pointToLayer: function (feature, latlng) {
// make sure `areaIcon` is an OPTIONS objects
return L.marker(latlng, areaIcon);
}
}).addTo(map); // Adding the entire geoJson layer to the map.
map.on("zoomend", function () {
var newMapZoom = map.getZoom();
if (newMapZoom >= 13) {
map.addLayer(harvestPoints);
} else {
// Removing entire geoJson layer that contains the points.
map.removeLayer(harvestPoints);
}
});
Side note: popups open on click by default, you should not need to add an on click listener for that?
Demo: http://jsfiddle.net/ve2huzxw/62/
I'm mixing up the choropleth example
and the layes control example
Using layers control with tiles, i've no problems, it works perfectly, but i need to work with geojson and this is my problem:
the gejson layer is ever in foreground and tiles on background.
but i need that when selecting a "streets" tile in layercontrol it come in foreground and l.geojson in backgrnd.
i need it to show labels. Using trasparency is not good for my purposes.
any solution?
here a part of the code:
var mapdataviz = L.mapbox.map('map', 'andria.h41061in')
.setView([39.0981, 16.5619], 8);
mapdataviz.legendControl.addLegend(document.getElementById('legend-content').innerHTML);
L.control.layers({
'city': L.mapbox.tileLayer('andria.cal_com_ief1'),
'com_geojson': L.geoJson(comData, {
style: getStyle,
onEachFeature: onEachFeature
}).addTo(mapdataviz),
'streets': L.mapbox.tileLayer('andria.h41061in')
},
{
'streets': L.mapbox.tileLayer('andria.h41061in'),
'com_geojson': L.geoJson(comData, {
style: getStyle,
onEachFeature: onEachFeature
}).addTo(mapdataviz),
'bounds': L.mapbox.tileLayer('andria.cal_conf')
}).addTo(mapdataviz);
var popup = new L.Popup({ autoPan: false });
// comData comes from the 'us-states.js' script included above
var comLayer = L.geoJson(comData, {
style: getStyle,
onEachFeature: onEachFeature
})
function getStyle(feature) {
return {
weight: 0.7,
opacity: 0.5,
color: 'white',
fillOpacity: 0.8,
fillColor: getColor(feature.properties.IEF1_2008)
};
}
You mention that transparency is not good for your purposes but this MapBox tutorial demonstrates how to put the geoJson layer behind the street map layer.
https://www.mapbox.com/blog/neighborhood-mapping-with-dynamic-vector-data-layers/
Is that helpful?
I'm using leaflet/JavaScript for the first time and I want to display a map, with a GeoJSON layer which change on every move… To only show points on the area.
This is my code source:
// Function to refresh points to display
function actualiseGeoJSON() {
// Default icon for my points
var defaultIcon = L.icon({
iconUrl: '../images/icones/cabane.png',
iconSize: [16, 16],
iconAnchor: [8, 8],
popupAnchor: [0, -8]
});
// We create each point with its style (from GeoJSON file)
function onEachFeature(feature, layer) {
var popupContent = '' + feature.properties.nom + "";
layer.bindPopup(popupContent);
var cabaneIcon = L.icon({
iconUrl: '../images/icones/' + feature.properties.type + '.png',
iconSize: [16, 16],
iconAnchor: [8, 8],
popupAnchor: [0, -8]
});
layer.setIcon(cabaneIcon);
}
// We download the GeoJSON file (by using ajax plugin)
var GeoJSONlayer = L.geoJson.ajax('../exportations/exportations.php?format=geojson&bbox=' + map.getBounds().toBBoxString() + '',{
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {icon: defaultIcon});
}
}).addTo(map);
}
// We create the map
var map = L.map('map');
L.tileLayer('http://maps.refuges.info/hiking/{z}/{x}/{y}.png', {
attribution: '© Contributeurs d\'OpenStreetMap',
maxZoom: 18
}).addTo(map);
// An empty base layer
var GeoJSONlayer = L.geoJson().addTo(map);
// Used to only show your area
function onLocationFound(e) {
var radius = e.accuracy / 2;
L.marker(e.latlng).addTo(map);
actualiseGeoJSON();
}
function onLocationError(e) {
alert(e.message);
actualiseGeoJSON();
}
function onMove() {
// map.removeLayer(GeoJSONlayer);
actualiseGeoJSON();
}
map.locate({setView: true, maxZoom: 14});
// Datas are modified if
map.on('locationerror', onLocationError);
map.on('locationfound', onLocationFound);
map.on('moveend', onMove);
I have tried to remove the layer in my first function but GeoJSONlayer is not defined
I have tried to remove the layer in onMove() but nothing appears
I have tried to remove the layer in moveend event but I have an syntax error…
If somebody can help me…
Sorry for my bad English, French guy ith french function names
I see you are using the leaflet ajax plugin.
The simplest way to get your map to work is to download all available data right at the start, providing a giant bounding box, and add it to the map just once. This will probably work just fine, unless there's insanely many cabins and stuff to download.
But if you wish to refresh the data regularly, based on the bounding box, you can use the refresh method in the leaflet-ajax plugin:
you can also add an array of urls instead of just one, bear in mind
that "addUrl" adds the new url(s) to the list of current ones, but if
you want to replace them use refresh e.g.:
var geojsonLayer = L.geoJson.ajax("data.json");
geojsonLayer.addUrl("data2.json");//we now have 2 layers
geojsonLayer.refresh();//redownload those two layers
geojsonLayer.refresh(["new1.json","new2.json"]);//add two new layer replacing the current ones
So initially:
var defaultIcon = ...
function onEachFeature(feature, layer) ...
// Do this in the same scope as the actualiseGeoJSON function,
// so it can read the variable
var GeoJSONlayer = L.geoJson.ajax(
'../exportations/exportations.php?format=geojson&bbox='
+ map.getBounds().toBBoxString() + '',{
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {icon: defaultIcon});
}
}).addTo(map);
And then for each update:
function actualiseGeoJSON() {
// GeoJSONLayer refers to the variable declared
// when the layer initially got added
GeoJSONlayer.refresh(
['../exportations/exportations.php?format=geojson&bbox='
+ map.getBounds().toBBoxString() + '']);
}
Alternatively, you could set the layer as a property of the map, instead of as a var:
map.geoJsonLayer = L.geoJson.ajax(...)
And later refer to it as follows:
map.geoJsonLayer.refresh(...)
this leaflet plugin is more suitable for your purpose, manage map events and zoom.
Caching remote requests and much more.
http://labs.easyblog.it/maps/leaflet-layerjson/
var ajaxUrl = "search.php?lat1={minlat}&lat2={maxlat}&lon1={minlon}&lon2={maxlon}";
map.addLayer( new L.LayerJSON({url: ajaxUrl }) );
Extend L.GeoJSON with more features and support ajax or jsonp request. See the source code comments for more documentation.