Say I have a geojson box I've added to leaflet. How can I allow the user to "click and drag the box" to a new location, which in turn updates all the coordinates automatically? I know how to edit the boundary/points that make up the shape using leaflet editing, but am not sure how to actually move the shape.
There is a Leaflet.Draw.Drag plugin for Leaflet Draw that allows you to move polygons when you enter edit mode. It does seem to be a bit finicky about the version, though. At least in a few quick experiments, I was only able to get it to work using Leaflet Draw version 0.2.3. If you have an existing L.GeoJson layer, you can simply specify that as the featureGroup in the edit options of the draw control:
var drawControl = new L.Control.Draw({
edit: {
featureGroup: yourGeoJsonLayer,
edit: {
selectedPathOptions: {
maintainColor: true,
moveMarkers: true
}
}
}
});
In the selectedPathOptions, the maintainColor option just keeps the existing style of the layer while you're editing, and the moveMarkers option places a little square marker in the middle of the polygon as a reminder that you can drag the whole thing rather than just edit the vertices.
Here is an example fiddle:
http://fiddle.jshell.net/nathansnider/qk5bsgn8/
Related
Im trying to bind geoserver WFS GetFeature request with BBOX and adding the geojson layer to Mapbox map object so that whenever map is panned and zoomed in/out, the geojson data within the map screen visible window will be downloaded and rendered instead of loading entire table geojson data. Here is the code snippet.
function geturl(){
return 'http://localhost:8080/geoserver/demo/ows?service=WFS&version=2.0.0&request=GetFeature&typeName=demo:assets&outputFormat=application/json'
+'&bbox='
+map.getBounds().getSouthWest().lat+','
+map.getBounds().getSouthWest().lng+','
+map.getBounds().getNorthEast().lat+','
+map.getBounds().getNorthEast().lng
}
map.on('load', () => {
map.addSource('city_assets', {
type: 'geojson',
data:geturl()
})};
Although I could see the points were loaded only in the viewing BBOX window for the first time, I don't see rest of the point data being downloaded and rendered when I zoom in/out or pan around.
It would be really helpful if someone can guide me if I have missed anything to make it working. Please feel free to ask for additional info. Thanks.
-Prem
I am new to leaflet, but am trying to implement a use case that I've been unable to find any examples or questions about here. Thank you in advance for helping with this question:
A live demo is here, and here's the code of interest in the GitHub repository.
As you mouseover the various geoJSON features, I use onEachFeature to change styling to 'highlight' that featured area on the map, and to display its name in the upper right info box:
function onEachFeature (feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight
});
layer.bindPopup(feature.properties.f2,customOptions);
}
var geojson;
geojson = L.geoJson(myData,{
style: style,
onEachFeature: onEachFeature,
}).addTo(map);
The problem arises where features overlap. When mousing over the overlapping regions only one is targeted. Instead, I would like all features overlapping at the cursor's position to be 'highlighted'; and to be able to list all the names in the info box.
I'm guessing that the solution is more like that I should retrieve the latlng on all mousemove events, determine if the latlng is in the boundary of any geoJSON objects, and if so, iterate through those highlighting and getting the names for all. I'm not sure if there is a plugin that can handle this more elegantly for me.
Is there anyway to target multiple overlapping geoJSON layers simultaneously in Leaflet?
You described an easy way, and I recommend you use it. I propose just one optimization for you.
Don't catch all mousemove events. You need a mouseover on each feature, and then check if there are other features overlapped by it.
function onEachFeature (feature, layer){
layer.on('mouseover',function(e){
var point = e.latlng;
map.eachLayer(function(layer){
var bounds = layer.getBounds();
if(bounds.contains(point))
highlite(layer);
})
})
}
Another way is to use the L.Canvas renderer and extend it so that it fires mouseover or other handlers for each layer under the pointer.
I have a layerGroup in my map which has a lot of markers and another layerGroup which has a lot of circles. I need to zoom in on these layer groups but I cannot find the exact API method to do so.
I have tried:
var myLayerGroup = L.layerGroup().addTo(map);
myLayerGroup.fitBounds(); // tried this
myLayerGroup.setBounds(); // and this too
I am not sure which method in the API will work for me. How to zoom in on a layer of markers?
Switch from using layerGroup to featureGroup, theb you can use getBounds() on a feature group to retrieve its bounds, then use map.fitBounds(result) to zoom to that view.
I'm using leaflet.draw, and when a rectangle is created, i'm fetching rectangle's data using layer.toGeoJSON(), and then i save it into a db using ajax.
After that, when the user display the map again, i'm loading previously saved data, and push them into the featureGroup reserved for leaflet.draw using L.GeoJSON.geometryToLayer()
Problem is that my previously created rectangle is now a real polygon for leaflet.draw.
"Rectangle" does not exist in geoJson specs, so i can understand that.
Now, in "properties" of the geojson, i know that the previous shape was a rectangle, with the "type" attribut.
My question is : is there a way to force a shape to be a rectangle in a leaflet.draw point of view ?
Thanks in advance !
I ran into this same problem and have come up with a solutions which works for me although it isn't the most elegant method.
Using leaflet.draw I receive a new layer on which I call layer.toGeoJSON() to save the rectangle to my database. On refresh of the page I'm pulling that GeoJSON representation back from my database and storing it with:
var geojson = JSON.parse(geojson_string);
What I tried first was to build my own Rectangle from the points and add it to drawnItems.
var bounds = L.latLngBounds(geojson.geometry.coordinates);
var rect = L.rectangle(bounds);
drawnItems.addLayer(rect);
This code did not throw an error, but it also didn't show a rectangle on the map. After further investigation I found the coordinate pairs output from layer.toGeoJSON() and the coordinate pairs needed by L.latLngBounds() were reversed (i.e. one was [lat, lng] and the other was [lng, lat]) which caused the Rectangle to be created but in entirely the wrong location. To get around this I constructed the layer first as a GeoJSON layer which results in a polygon, but then use that representation's bounds to construct my Rectangle.
var geojson_layer = L.GeoJSON.geometryToLayer(geojson);
var rect = L.rectangle(geojson_layer.getBounds());
drawnItems.addLayer(rect);
This successfully creates a Rectangle which leaflet.draw recognizes and allows for the edit tools to work correctly.
Has anyone ever tried to use Leaflet Clustering Plugin + Marker Rotation Plugin? I tried to work with both but they work partially.
In a first view, I can see some clusters and some isolated (and rotated) markers. Every time I zoom in into some Cluster the rotated markers disappear. Does anyone have any idea why this happens?
to simply rotate a marker, use :This Leaflet Plugin
include this in your html :
<script src="../leaflet-plugin/Marker.Rotate.js"></script>
wen create a marker :
var marker = new L.Marker(map.getCenter(), {iconAngle: 90});
a complete example
Found a solution provided by Dave Leaver..it works perfectly.
"You can hack it to work with L.MarkerClusterGroup (so it is no worse than it is already) by changing the start of the update function in the rotate plugin to bail if there is no _icon:
update: function() {
if (!this._icon) {
return;
}
The problem is that the rotate plugin is overwriting the transform and fighting with leaflet on it.
I recommend instead using a DivIcon with a child element that has the rotation, that way leaflet can happily update the transform to move the marker independent of the rotation.
As a totally broken example:
var m = new L.Marker(getRandomLatLng(map), { icon: L.divIcon({html:'<img src="http://cdn.leafletjs.com/leaflet-0.5.1/images/marker-icon.png" style="-webkit-transform: rotate(39deg); -moz-transform:rotate(39deg);" />'})});"