I am currently creating a webmap with leaflet. I used leaflet.ajax to import polygons from a geojson. But the new polygon layer covers the basemap, resulting in the polygons on a white background.
https://virgilxw.github.io/Singapore_Election_1955/
If you go the github page and navigate to the layer menu, you can find the polygon layer under "Data".
I have tried re-ordering the layers, but moving the base map above the polygons just result in the polygons being covered.
// Default base Map
map.addLayer(layerOneMapSG_Default);
// Add geojson
var Layer1955Wards = new L.GeoJSON.AJAX("data/wards1955.geojson");
// Styled Layer Control
var baseMaps = [
{
groupName: "Base Maps",
expanded: true,
layers: {
"OneMap": layerOneMapSG_Default
}
}];
var overlays = [
{
groupName: "data",
expaned: "true",
layers: {
"Constituencies": Layer1955Wards
}
},
{
groupName: "Map Overlays",
expanded: "true",
layers: {
"1953 Topological": Layer1953Topo,
"1953 Aerial Photographs": Layer1953Aerial
}
}];
var styledLayerControlOptions = {
container_width: "300px",
container_maxHeight: "350px",
group_maxHeight: "80px",
exclusive: false
};
var styledLayerControl = L.Control.styledLayerControl(baseMaps, overlays, styledLayerControlOptions);
map.addControl(styledLayerControl, overlays);
Related
I'm working with Mapbox GL JS to plot geoJSON data on a map using their external geoJSON example as a starting point. The geoJSON file contains lots of features which are plotted as individual markers on the same layer. I would like to highlight the clicked marker by changing its colour from red to blue. I have adapted the example to show a pop-up with the point id when clicked (just as a proof of concept that the markers can fire events when clicked), however, I'm struggling to find a way to change the styling of the individual clicked marker.
The code is currently as follows:
mapboxgl.accessToken = 'pk.eyJ1IjoiZGFuYnJhbWFsbCIsImEiOiJjbDB3ODFveHYxOG5rM2pubWpwZ2R1Y2xuIn0.yatzJHqBTjQ6F3DHASlriw';
const map = new mapboxgl.Map({
container: 'map', // container ID
style: 'mapbox://styles/mapbox/satellite-v9', // style URL
zoom: 7, // starting zoom
center: [138.043, 35.201] // starting center
});
map.on('load', () => {
map.addSource('earthquakes', {
type: 'geojson',
data: 'https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson'
});
map.addLayer({
'id': 'earthquakes-layer',
'type': 'circle',
'source': 'earthquakes',
'paint': {
'circle-radius': 8,
'circle-stroke-width': 2,
'circle-color': 'red',
'circle-stroke-color': 'white'
}
});
});
map.on('click', 'earthquakes-layer', (e) => {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML('Id: ' + e.features[0].properties.id)
.addTo(map);
});
Here is a codepen: https://codepen.io/danb1/pen/BaYjOyx
Is it the case that it's actually not possible to use this approach, and instead each feature from the geoJSON file needs to be plotted as a separate layer? I'm struggling to find any examples of this and am not able to modify the geoJSON source — it has to come from one single file (rather than loading multiple geoJSON files separately on separate layers).
This is possible using feature-state. The first thing to do is to ensure the layer data contains ids for each feature (in the example the source data doesn't so we need to add generateId: true to the map.addSource method).
We then need to add mousemove and mouseleave events to the map to store the moused-over feature id (if there is one, i.e. if the mouse is hovering over a feature):
let hoveredEarthquakeId = null;
map.on('mousemove', 'earthquakes-layer', (e) => {
map.getCanvas().style.cursor = 'pointer';
if (e.features.length > 0) {
map.setFeatureState(
{ source: 'earthquakes', id: e.features[0].id },
{ hover: true }
);
hoveredEarthquakeId = e.features[0].id;
}
});
map.on('mouseleave', 'earthquakes-layer', () => {
map.getCanvas().style.cursor = '';
if (hoveredEarthquakeId !== null) {
map.setFeatureState(
{ source: 'earthquakes', id: hoveredEarthquakeId },
{ hover: false }
);
}
hoveredEarthquakeId = null;
});
Finally, in the layer properties, the colour setting of the circle needs to be updated to reflect the hover value stored against the feature:
'circle-color': [
'case',
['boolean', ['feature-state', 'hover'], false],
'#00f',
'#f00'
],
The final thing can be seen in the modified pen. There is also a MapBox tutorial covering this kind of thing in a slightly more complicated way, which I hadn't come across until now: https://docs.mapbox.com/help/tutorials/create-interactive-hover-effects-with-mapbox-gl-js/.
I am trying to get the layer details of the map which are already overlay on the map. When leaflet draw is created I want to get the layer details (Not the polygon coordinates created by leaflet draw plugin) so that I can use them.
I am able to get the coordinates of drawn polygon but that's not what I want.
var draw_layer = new L.FeatureGroup();
mymap.addLayer(draw_layer);
var drawControlFull = new L.Control.Draw({
draw: {
polygon: {
allowIntersection: false, // Restricts shapes to simple polygons
drawError: {
color: '#e1e100', // Color the shape will turn when intersects
message: '<strong>Oh snap!<strong> you can\'t draw that!' // Message that will show when intersect
},
shapeOptions: {
color: '#97009c'
}
},
// disable toolbar item by setting it to false
polyline: false,
circle: false,
rectangle: false,
marker: false,
circlemarker: false
},
edit: {
featureGroup: draw_layer,
remove: true
}
});
mymap.addControl(drawControlFull);
mymap.on(L.Draw.Event.CREATED, function (e) {
var type = e.layerType, layer = e.layer;
if(type === 'polygon'){
var _ajax_cords = [];
var _coords = layer.getLatLngs()[0];
$.each(_coords,function(ind,val){
var _te_co = {x : val.lat, y : val.lng};
_ajax_cords.push(_te_co);
});
}
//if (type === 'polygon') {layer.bindPopup('A popup!');}draw_layer.addLayer(layer);
});
Well I can get the marker detail as I get lot of posts on that but didn't see a post how to get the polygon details.
Any help on this is much appreciable
Steps to reproduce
Steps to reproduce the behavior:
Go to https://virgilxw.github.io/Singapore_Election_1955/
Click on the top right button on the map
click on "data"
click on "constituencies"
Expected behavior
Polygons should overlay base map
Current behavior
base map covered by grey-colored layer
Leaflet version:1.51.1
Browser (with version):
OS/Platform (with version):
Additional context
``
// Default base Map
map.addLayer(LayerOSM);
// Add geojson
var Layer1955Wards = new L.GeoJSON.AJAX("data/wards1955.geojson");
// Styled Layer Control
var baseMaps = [
{
groupName: "Base Maps",
expanded: true,
layers: {
"OneMap": LayerOneMapSG_Default,
"OSM": LayerOSM
}
}];
var overlays = [
{
groupName: "data",
expaned: "true",
layers: {
"Constituencies": Layer1955Wards
}
},
{
groupName: "Map Overlays",
expanded: "true",
layers: {
"1953 Topological": Layer1953Topo,
"1953 Aerial Photographs": Layer1953Aerial
}
}];
var styledLayerControlOptions = {
container_width: "300px",
container_maxHeight: "350px",
group_maxHeight: "80px",
exclusive: false
};
var styledLayerControl = L.Control.styledLayerControl(baseMaps, overlays, styledLayerControlOptions);
map.addControl(styledLayerControl, overlays);
Is it possible to add a "target overlay" for Leaflet Draw toolbar?
For example I could have two overlays such as Areas and Points of interest.
Now, I would like to add markers only to Points of Interest overlay and polygons on Areas overlay.
I've been trying to figure out that is it somehow possible to programmatically activate overlays or assign overlay for different draw toolbars but nothing seems to help.
All new layers are added to same overlay since I can't figure out which overlay toolbar is used.
And at least console log value of events don't seem to help and I cannot figure out that which toolbar was used (I could use it to force addLayer to use certain overaly), I cannot get anything regarding the target layer etc.
var poiLayer = new L.FeatureGroup();
var areaLayer = new L.FeatureGroup();
var options = {
polygon: {
allowIntersection: false,
drawError: {
color: "#e1e100",
message: "<strong>Lines of a polygon cannot overlap!</strong>"
},
shapeOptions: {
color: "#FF5656"
}
},
polygon: {
allowIntersection: false,
drawError: {
color: "#e1e100",
message: "<strong>Lines of a polygon cannot overlap!</strong>"
},
shapeOptions: {
color: "#FF5656"
}
},
edit: {
featureGroup: areaLayer,
poly: {
allowIntersection: false
},
poly: {
allowIntersection: false
},
poly: {
allowIntersection: false
}
},
draw: {
featureGroup: areaLayer,
name: "dafuq2",
polygon: {
allowIntersection: false,
showArea: true
},
},
name: "namne123123123"
};
//same for the poiLayer
var drawControl = new L.Control.Draw(options);
map.addControl(drawControl);
var drawControl2 = new L.Control.Draw(options2);
map.addControl(drawControl2);
map.on(L.Draw.Event.CREATED, function(e) {
console.log(e);
});
I am using mapbox.js to render a mapbox map. I am trying to load geojson from my server that contain either a country polygon or a city coordinates (lon,lat).
I have been able to style the country polygons but not the city points/markers.
I am not able to modify the geojson to use mapbox simplestyle
Here is the code executed when the page loads (I changed the mapbox map ID):
var southWest = L.latLng(-90, -360), northEast = L.latLng(90, 360);
var bounds = L.latLngBounds(southWest, northEast);
var map = L.mapbox.map('map', 'MapboxMapID', { zoomControl: false, infoControl: true, detectRetina: true, maxBounds: bounds, minZoom: 2, legendControl: {position: 'topright'}});
new L.Control.Zoom({ position: 'bottomright' }).addTo(map);
map.fitBounds(bounds);
var locationsGroup = L.featureGroup().addTo(map);
and then when the user selects a country or city with a selectbox:
$("#select2-search-up").on("change", function (e) {
if (e.added) {
var location = L.mapbox.featureLayer().loadURL('/citiesCountriesID/' + e.added.id).on('ready', function(featLayer) {
this.eachLayer(function(polygon) {
polygon.setStyle({
stroke:false, fillColor:'red', fillOpacity:0.2
});
});
});
locationsGroup.addLayer(location);
} else {
locationsGroup.eachLayer(function (layer) {
if (layer._geojson[0]._id == e.removed.id) {
locationsGroup.removeLayer(layer);
}
});
}
});
Ideally I would like to display a different icon that the standard marker, but I could do with a small red square
Thank you for your inputs
In this example I did some circle markers but I'm pretty sure you can do other basic svg shps or your own .png pretty easy. http://bl.ocks.org/mpmckenna8/db2eef40314fe24e9177
This example from Mapbox also shows how to use a icon from their icon Library which has a lot of choices also. https://www.mapbox.com/mapbox.js/example/v1.0.0/l-mapbox-marker/
It might also help to see some of your geojson structure to see why it can't use simplestyle
In my bl.ocks example I loaded each of the geojson datasets separately
var begin = L.geoJson(start,{
pointToLayer:function(feature, latlng){
return L.circleMarker(latlng,{
radius:9,
fillColor: "orange",
fillOpacity:.7
})
}
})
Is how I set up my circles and I set a different L.geoJson to the other data which I left as the default markers.