I have a leaflet map with an overlay made from a geojson file that contains polygons, lines and points. I'd like to be able to use custom markers (let's say the image marker is CustomMarker.png). So far, I have the following code that works perfectly well, the only thing is that it displays standard marker icons :
$.getJSON(url, function(geojson) {
overlay = L.geoJson(geojson, {
style: function(feature) {
return {
fillColor: 'red',
weight: 1,
opacity: 0.5,
color: 'red',
dashArray: 3,
fillOpacity: 0.5,
}
},
onEachFeature: function(feature, layer) {
layer.bindPopup("<strong>" + layer.feature.properties.Titre + "</strong><br/>" + " : nom de la région")
}
}).addTo(map);
I know the solution is at my grasp and that something should be put just above "onEachFeature" but can't figure it out so far.
Related
PLease see this jsfiddle (scroll down in the JS window to below the geoJSON)
https://jsfiddle.net/n3zerj2q/1/
var prevLayer = null;
var map = L.map("map").setView([30, 0], 3);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var noStyle = {
fillColor: "#fff",
weight: 1,
opacity: 1,
color: 'red',
dashArray: '3',
fillOpacity: 0
};
var myGeojSonLayerGroup = L.geoJson(world, {
onEachFeature: onEachFeature2
}).addTo(map);
function onEachFeature2(feature, layer) {
if (feature.properties && feature.properties.name) {
layer.bindPopup('<span class="pcA">' + feature.properties.name + '</span>')
}
layer.setStyle(noStyle);
layer.on({
mouseover: function (e) {
e.target.openPopup();
if (prevLayer !== null) {
// Reset style
prevLayer.setStyle(styleA());
}
var thisLayer = e.target;
thisLayer.setStyle(styleX())
prevLayer = thisLayer;
}
});
}
function styleA() {
return {
fillColor: "#fff", fillOpacity: 0.0
};
}
function styleX() {
return {
fillColor: "pink", fillOpacity: 0.4
};
}
It simply displays a world map and as the user rolls over country a popup appears with the country name (as well as some color styling) - mostly this is positioned "sensibly" more or less in the middle of the country, but for some (esp bigger ones) it's way off - eg the USA, China, Russia, Argentina...
I'm not setting the position of these - leaflet is, somehow... Other than editing the (large) geoJSON to include anchor points for each country, I wonder if there's some way of tweaking whatever leaflet is doing? Why, for example, does it place Antarctica's where it does? Or China's? etc....
So when a Popup is about to be shown, it will check where, in this specific bit of code:
if (!latlng) {
if (source.getCenter) {
latlng = source.getCenter();
} else if (source.getLatLng) {
latlng = source.getLatLng();
} else if (source.getBounds) {
latlng = source.getBounds().getCenter();
} else {
throw new Error('Unable to get source layer LatLng.');
}
}
So for popups without an explicit latlng, the position will dpend on themethods available on the source layer - this means that for Rectangles and ImageOverlays that'll run getBounds().getCenter(), for Markers and Circles that'll run getLatLng(), and for Polylines and Polygons that'll run getCenter().
The getCenter() method from Polygon just delegates the work elsewhere:
return PolyUtil.polygonCenter(this._defaultShape(), this._map.options.crs);
...and, finally, the polygonCenter() function will calculate the polygon's centroid.
Note that the implementation only takes into account the first ring of the polygon:
if (!LineUtil.isFlat(latlngs)) {
console.warn('latlngs are not flat! Only the first ring will be used');
latlngs = latlngs[0];
}
This is due to the centroid algorithm only being able to handle "simple" polygons, with just an outer ring. Remember to read the OGC SFA specification for a refresher on (multi)polygon rings.
I have a leaflet map using leaflet-realtime to display and update a position, polygon and line from a geoJson source (data is the position and field of view from an airborne camera). I want to change the style of the line and polygon from the default blue. I understand the leaflet-realtime extends L.geojson so I thought the following code should work but I get options.style is not a function. I have been looking at other examples to try and do this but have spent the day frustrated.
var lineStyle = {
color: 'black',
weight: 5,
opacity: 0.5
}
los = L.realtime({
url: 'http://127.0.0.1/geojson/los2.geojson',
crossOrigin: true,
type: 'json'
}, {
interval: 1 * 500,
style: lineStyle
}).addTo(map);
los.on('update', function(){
map.flyTo(
[this._features.los.geometry.coordinates[1][1],
this._features.los.geometry.coordinates[1][0]]
)
});
If anyone can point me in the right direction it would be hugely appreciated.
Thanks
Yes options.style must be a function - look at:
https://leafletjs.com/reference-1.7.1.html#geojson-style
Change your code:
var lineStyle = {
color: 'black',
weight: 5,
opacity: 0.5
}
los = L.realtime({
url: 'http://127.0.0.1/geojson/los2.geojson',
crossOrigin: true,
type: 'json'
}, {
interval: 1 * 500,
style: function() { return lineStyle; }
}).addTo(map);
los.on('update', function(){
map.flyTo(
[this._features.los.geometry.coordinates[1][1],
this._features.los.geometry.coordinates[1][0]]
)
});
In leaflet, I can visualize the geojson layers using following script;
L.geoJSON('district.json', {
style: myStyle,
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.name);
}
}).addTo(map);
The above code shows the features on the map and also show the name properties when clicked on map. But what I want is different. I want to hide the feature of the district.json on map, but It should be appear the popup content when I clicked on the feature position. I tried following style;
var myStyle = {
fillColor: rgb(0,0,0,0),
opacity: 0,
strokeOpacity: 0,
}
This will hide the layers, but when I clicked on the map, nothing will popup. Is there any possible styles for this conditions?
You can simply change the value of opacity to 0.01 so that the layer will disappear from the map but there still remaining the popup content.
For this change your myStyle variable in following way;
var myStyle = {
fillColor: rgb(0,0,0,0.01),
opacity: 0.01,
strokeOpacity: 0.01,
}
You could use circle markers as following:
L.geoJSON('district.json', {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {color: 'transparent', fillColor: 'transparent', radius: 20});
},
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.name);
}
}).addTo(map);
This way, you add a transparent, non-visible circle marker for each feature. You can also try different radius values that will lead to larger or smaller clickable areas.
I'm working on a map with a few circleMarkers. When a user is clickin on one of this circleMarker, I would like to center the map on this circleMarker and to zoom in. It works when I try this on multipolygon layers, but I didn't succeed on circleMarkers. Does anyone can help me?
Here is the code for my circleMarkers:
<script>
var map = L.map('map', {
center: [41.8, 12.5],
zoom: 5,
zoomControl:true, maxZoom:15, minZoom:4,
});
var feature_group = new L.featureGroup([]);
var raster_group = new L.LayerGroup([]);
var basemap = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri',
});
basemap.addTo(map);
function style1(feature) {
return {
weight: 2,
radius: 10,
opacity: 1,
color: 'black',
weight: 1,
fillOpacity: 1,
fillColor: 'red'
};
}
L.geoJson(villes, {
style: style1,
pointToLayer: function (feature, latlng)
{
return L.circleMarker(latlng).bindLabel( feature.properties.Name, {className: "ville", noHide: true });
}
}
)
.addTo(map)
.showLabel;
</script>.
Here is a link to the complete map.
Thank you.
This can be achieved really simply.
Let's assume marker points to your leaflet marker and map to your leaflet map.
Quick way (recommended)
marker.on("click", function(event) {
map.setView(marker.getLatLng(), 16);
}, marker);
Here, I don't even compute the needed zoom level, because I assume leaflet will have to zoom to its max level anyway.
I could also have added my marker to a L.LayerGroup, even if the main point of a LayerGroup is to group multiple markers.
Anyhow, the more precise way
marker.on("click", function(event) {
map.setView(marker.getLatLng(), map.getBoundsZoom(layerGroup.getBounds());
}, marker);
Note that the quick way will do it nicely too. The second solution might seem more precise but it also slower, and implies a use of LayerGroup which is not the way it has been designed to work (create a new layergroup for each marker).
Don't forget to take yout time reading the docs, it's well-designed and pretty easy to understand.
I find the solution:
function onClick(e) {map.setView(this.getLatLng(),15);}
L.geoJson(villes, {
style: style1,
pointToLayer: function (feature, latlng)
{
return L.circleMarker(latlng).bindLabel( feature.properties.Name, {className: "ville", noHide: true }).on('click', onClick);
}
}
)
.addTo(zoom1)
.showLabel;
Thanks Stranded Kid for your help.
I am trying to set style for related layers in a featureGroup using Leaflet API, here is my code:
var highlightStyle = {
color: '#9b1d41',
weight: 3,
opacity: 0.6,
fillOpacity: 0.65,
fillColor: '#9b1d41'
};
$wnd.mapareas.eachLayer(function(layerOnMap) {
layerOnMap.setStyle(highlightStyle);
console.log(layerOnMap);
});
I could see in the log that layer has new set style , but its not visible on map, like color is not changed.
For GeoJSON layers (which are FeatureGroups) you could do like this
new L.GeoJSON(mp, {
style: highlightStyle
});
For standard FeatureGroup
new L.FeatureGroup([mp1, mp2]).setStyle(highlightStyle);