I would like to be able to fitBounds to a feature when you click on it, but when it zooms in I'd like it to take into account a control layer that will appear once zoomed in, and zoom in but just about 150px to the left. Currently I can accomplish this with the following code, but unfortunately it's not a smooth zoom because my current method will zoom using fitBounds and then once zoomed it uses panBy to pan 150px to the left. This wouldn't be so bad if the panning was smooth, perhaps maybe after a 250ms wait. Ideally I would like to be able to do some math on the bounds passed to the fitBounds method to simply account for the 150px shift to the left.
Here is an example of what I currently have working.
Here is a simplified version of the code I'm using: (you may click here for a fully working version with all of the source code)
when you click
function clickFeature(e) {
var layer = e.target;
map.fitBounds(layer.getBounds());
}
map on zoomEnd:
map.on({
zoomend: function() {
map.panBy([150, 0]);
}
});
So, I've achieved the desired function, but it's just not smooth.
Is there a way to just do some math on the bounds that we're getting for the clicked feature so that when we zoom we zoom into an already modified coordinate, thus eliminating the two-step animation process?
First of all, you can control the animation using pan options. This could help you make the transition smoother.
You can see those here.
Second, you can calculate the offset that you need by using the conversion functions. These can be seen here.
For example, you could do something like (off the top of my head) use getBoundsZoom for the map object on the polygon bounds to figure out your future zoom, then use that zoom in the project function with the polygon and create a new LatLngBound from the polygon bound that is slightly offset.
Hope this helps!
I had this same issue, and if was easier than I had thought!
You can set padding on the fitBounds method (and all the pan/zoom methods for that matter)
http://leafletjs.com/reference.html#map-fitboundsoptions
so:
map.fitBounds(layer.getBounds(),{paddingBottomRight:[150,0]});
Related
I'm using Leaflet Draw to draw rectangles on a Leaflet map. The rectangles get added to a FeatureGroup once they are created, and their styles are updated based on their size. For example, the rectangles are filled red if their area exceeds a certain threshold and green if their area is within the threshold.
I'm leveraging the "draw:created" callback to inspect the completed rectangle's size. I'm also able to update the rectangle's style during editing by leveraging the "draw:editresize" and "draw:editmove" callbacks. By doing this, users can easily see if their rectangles fall within the correct area requirements while they are resizing them.
Here is my problem: I haven't been able to find a callback that allows me to style the rectangle during its initial creation. Have I overlooked a callback? I've tried all of the logical ones from the doc's: https://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html#l-draw-event.
There's not really any code to show other than the following event handlers, which currently work while editing a rectangle.
this.map.on('draw:editmove', function (e) {
self.setROIStyle(e);// works
});
this.map.on('draw:editresize', function (e) {
self.setROIStyle(e);//works
});
Thanks,
Ray
I've been trying different tactics with leaflet map to zoom ignoring the default fixed zooming steps of the library, but without any luck so far. Through the following function:
window.addEventListener('mousewheel', function(e){
if (!e) e = event;
var direction = (e.detail<0 || e.wheelDelta>0) ? 1 : -1;
},
false);
I would like to achieve a smooth zooming effect like the one in Google Maps, which tracks the zoom based on deltaY and mouse scroll event. Do you know how to solve this issue or do you know a reference I could look at?
Thanks in advance for your replies!
Set the zoomSnap option of the map to zero. See also the wheelPxPerZoomLevel option.
Please note that fractional zoom is a feature introduced in Leaflet 1.0.0. This means that previous versions are not able to use non-integer zoom levels at all.
I am using leaflet.js to create few markers and circles. I am using the below given code to draw circles : -
L.circle([ lat, lng ], 1000, {
color : colorCode,
stroke : false,
fillColor : colorCode,
fillOpacity : 0.7
});
Now if I edit this circle on UI and drag this circle vertically downwards, the circle size increases and vice a versa. Similar issue is with calling the above given method with different lat lngs. The same radius (1000) sized circle get plotted with different sizes on map.
My requirement is to place marker with same radius with same size on map everywhere.
I checked L.circleMarker but it takes radius in pixels and also circleMarkers does not scale in zoomin zoomout events. That is why I can't use circleMarkers.
I changed the crs option to 4326 but no success. I am using imageOverlay not tileset. I have created a fiddle.
http://jsfiddle.net/newBee_/88bdrzkr/12/
Try creating a circle on top area then edit and move it downwards. It's size increases. This is what I want to stop. This will resolve the problem of generating circle of same radius via code in different area of map with same size. Please help.
Please suggest.
Edit:
It looks like this is a bug deep into Leaflet 0.x: L.Circle radius computation uses hard-coded Earth projection rather than the specified CRS. Leaflet 1.0 seems to correctly check for the CRS before using the Earth-related computation.
For your case, simply overriding the faulty method seems to fix it, at least visually.
Demo: http://jsfiddle.net/88bdrzkr/13/
The "corrected" method to include in your script:
L.Circle.include({
_getLngRadius: function () {
return this._getLatRadius();
}
});
Regarding iH8's answer, the trick to override L.CRS.Simple.scale is similar to highly zooming (the 256 factor expands the latLng to much further pixels - any high number will do). At high zoom, you are moving your circle along a very short distance, for which the latitude does not change much. So you do not see any visible difference in radius, even though the bug is still there.
Demo of using just higher zoom, no method override at all: http://jsfiddle.net/kau6g8fk/1/
For your need where the circle looks to be more like a visual aid, any of these 3 solutions is enough.
Edit: the CRS is not the issue at all.
Previous message:
If you use Leaflet for indoor mapping, as your jsFiddle suggests (or any flat type map, as opposed to the projection of a sphere like Earth on to a plane), you could simply use L.CRS.Simple
Striked out this faulty solution as pointed out by Ghybs in his answer
Very weird issue, turns out that overloading L.CRS.Simple's scale method to return 256 * Math.pow(2, zoom) fixes this. Here's a fork of your JSFiddle: http://jsfiddle.net/kau6g8fk/ I'm unsure as to the cause of this issue, it would require more research. Will do if i find the time. Found the solution here: http://codepen.io/mike_beweb/pen/BymKGe
The answer below was given before the poster edited his/her question and showed that the used CRS was L.CRS.Simple while i presumed the default CRS. I'll leave it in tact because it might come in handy for some users:
The size change on drag of your L.Circle's is because of your map's default spherical mercator projection (EPSG:3857). Best explained with an image, here's a map with a graticule overlay on every 10 degrees:
Demo on Plunker: Leaflet 0.7.5 EPSG:3857 Spherical
As you move further from the equator every plane becomes higher. Thus your circle automaticly becomes higher the further north/south you drag it. You could use a equirectangular projection (EPSG:4326), in which every plane has the same size regardless of the distance from the equator:
Demo on Plunker: Leaflet 0.7.5 EPSG:4326 Equirectangular
With equirectangle projection you won't have the problem you're having now but you'll have to change your tileset to one with EPSG:4326 projection and those are hard to come by compared to EPSG:3857 tilesets.
If you're not willing or unable to change projection another solution could be to hack around L.CircleMarker and change the radius of your markers depended on current zoomlevel. But that's rather ugly in my opinion.
I am coding in JavaScript using the Google Maps API, and I was curious if there was a way to set the priority of what polygon array info window is shown when I click on an area. I have two polygons that are overlapping, and I need to control which info bubble appears when you click on the overlapped area. Thank you!
The click will be triggered on the most top Polygon.
The order of the polygons usually depends on the order in which they have been added to the map(when the map-property has been set) or by setting a custom zIndex-property.
So when you want to define a priority you must define the zIndex for the Polygons.
When you want to be able to click on each polygon(and each part of each polygon) there is a simple approach:
Observe the mouseover of the polygons and set the zIndex of the hovered polygon to a value higher than the zIndex of the other polygons. This will bring the polygon into front and you now may also click on the previously covered area.
You may implement this by extending the polygon-prototype:
(function(){
var a=z=0;
google.maps.Polygon_=function(opts){
this.setValues(opts)
google.maps.event.addListener(this,'mouseover',function(){
this.set('zIndex',++z);
});
google.maps.event.addListener(this,'rightclick',function(){
this.set('zIndex',--a);
});
};
google.maps.Polygon_.prototype = google.maps.Polygon.prototype;
google.maps.Polygon = google.maps.Polygon_;}
)();
Demo: http://jsfiddle.net/doktormolle/wznd5nsy/
(Use rightclick to send a polygon to back, e.g. when it completely covers another polygon).
I'm using svg-pan-zoom library and I need to pan/zoom the view to fit a particular element.
I could use fit method but it fits the whole content in this case I need to fit only one particular element.
Another option can be to calculate the pan and zoom required and use the custom control, but how to get the pan/zoom of an element to fit the window?
UPDATE
I tried to follow the #bumbu "easier" solution. That was my first thought but I have encountered some troubled with the zooming point position.
This is a fiddle to show the expected behaviour and the calculation attempt.
http://jsfiddle.net/mgv5fuyw/2/
this is the calculation:
var bb=$("#target")[0].getBBox();
var x=bb.x+bb.width/2;
var y=bb.y+bb.height/2;
But somehow the zooming center expected (225,225) is not the right one.
I found a solution panning before zooming, I could not find the right way to use zoomAtPoint() method.
http://jsfiddle.net/mgv5fuyw/3/
var bb=$("#target")[0].getBBox();
var vbb=panZoomInstance.getSizes().viewBox;
var x=vbb.width/2-bb.x-bb.width/2;
var y=vbb.height/2-bb.y-bb.height/2;
var rz=panZoomInstance.getSizes().realZoom;
var zoom=vbb.width/bb.width;
panZoomInstance.panBy({x:x*rz,y:y*rz});
panZoomInstance.zoom(zoom);
Without going into detail I'd try 2 approaches:
Easier:
Init the svg-pan-zoom library
Fit and center you SVG
Calculate positions (top-left and bottom-right, or center and size) of the elements you're interested in
Now based on viewport size you should be able to calculate zoom level and center point of each element
Harder:
Figure out relative position of the original objects relative to original viewport
Based on current viewport size you should be able to calculate zoom level and center point of each element