Can someone provide an explanation on how to use the Leaflet Marker Icon XY Coordinates listed here:
http://leafletjs.com/examples/custom-icons/
Is lng/lat directly mapped to x/y? For example, sometimes in game engines, the Y pixel increases in value, but goes down the page.
Here is it the same? I can't quite wrap my head around it.
Not exactly sure what you mean by "Is lng/lat directly mapped to x/y?", but here are some explanations that should talk enough:
(tile courtesy MapQuest)
As in most image manipulation software:
X increases from left to right
Y increases from top to bottom
When specifying iconAnchor and shadowAnchor for Leaflet custom icons, these directions still apply. Furthermore, like in most image software as well, the origin is the top left corner of your image.
var myIcon = L.icon({
iconUrl: 'path/to/image.png', // relative to your script location, or absolute
iconSize: [25, 41], // [x, y] in pixels
iconAnchor: [12, 41]
});
As explained in the doc, if you specify iconSize but not iconAnchor, Leaflet will assume your icon tip is at the center of your image and position it accordingly (same for shadow).
But if you do specify neither iconSize nor iconAnchor, Leaflet will position your icon image "as is", i.e. as if its tip was its top left corner. Then you can apply a className option and define it in CSS with negative left and top margins to re-position your image.
var myIcon = L.icon({
iconUrl: 'path/to/image.png',
// iconSize: [25, 41],
// iconAnchor: [12, 41], // [x, y]
className: 'custom-icon'
});
.custom-icon {
margin-left: -12px; /* -x */
margin-top: -41px; /* -y */
}
This usage might be more interesting when using a DivIcon, for which you may not know the size in advance, and use CSS transforms to position it.
As for the popupAnchor, it uses the icon tip as origin, so you will most likely specify a negative y value, so that the popup appears above the icon.
popupAnchor: [1, -34] // [x, y]
Finally when adjusting your anchor values, a useful trick is to add a normal default marker at the exact same Lat/Lng location as the marker with your custom icon, so that you can compare both icon tip positions easily.
Related
I'm trying to add circles to my map, but for some reason the circles only show as dots, irrespective of the radius size.
var circle = L.circle(map.unproject([9541, 7658], map.getMaxZoom()), {
radius: 500
}).addTo(map);
I'm using pixel coordinates, but as you can see I'm converting them, so even though I only get dots on the map, they show at the right coordinates. I would hope this isn't the issue, but...?
I've successfully added circleMarkers, but the radius doesn't grow when zooming. At least not that I could see.
So the question is: how can I get the dots to show as circles?
Using Leaflet 1.9.3
Update
It appears that with pixel coordinates you need to enter a really high value for the radius. Thought I had already tried this before asking the question but apparently not.
var circle = L.circle(map.unproject([9541, 7658], map.getMaxZoom()), {
radius: 50000
}).addTo(map);
Unfortunately they're all showing at different sizes, even with the same radius, but that's a different question...
I originally misread your question and gave an incorrect answer, sorry. Circle radius is static. I think that the best way to change it with zoom level would be to use a zoom event listener:
let currZoom = map.getZoom();
let circles = [/* Store your circles here as you create them */];
map.on("zoomend", () => {
const zoomDiff = map.getZoom() - currZoom;
currZoom = map.getZoom();
for (const circle of circles) {
circle.setRadius(circle.getRadius() * 2 ** zoomDiff);
}
});
It's been a while since I've worked with Leaflet, but I think that will do the trick.
Edited to account for your comment regarding multiple circles.
I am using leaflet plugin to show google map with marker and polyline.
When I use default marker I am getting marker attached properly with polyline.
but when I changed the default marker with small circle icon image then that is not properly attached .
I am attching the screenshot . Please let me know How can I solve this ?
As far as I remember, there are some heights/widths You need to give when changing markers, as the center of the marker is not at the coordinate it depicts.
This example from the documentation shows that You set them on the Icon
var myIcon = L.icon({
iconUrl: 'my-icon.png',
iconSize: [38, 95],
iconAnchor: [22, 94],
popupAnchor: [-3, -76],
shadowUrl: 'my-icon-shadow.png',
shadowSize: [68, 95],
shadowAnchor: [22, 94]
});
L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
I want to use ImageOverlays as markers, because I want the images to scale with zoom. Markers icons always resize to keep their size the same when you zoom.
My problem is that I can't figure out how to transform pixels to cords, so my image isn't stretched.
For instance, I decided my south-west LatLng to be [50, 50]. My image dimensions are 24px/24px.
How do I calculate the north-east LatLng based on the image pixels?
You are probably looking for map conversion methods.
In particular, you could use:
latLngToContainerPoint: Given a geographical coordinate, returns the corresponding pixel coordinate relative to the map container.
containerPointToLatLng: Given a pixel coordinate relative to the map container, returns the corresponding geographical coordinate (for the current zoom level).
// 1) Convert LatLng into container pixel position.
var originPoint = map.latLngToContainerPoint(originLatLng);
// 2) Add the image pixel dimensions.
// Positive x to go right (East).
// Negative y to go up (North).
var nextCornerPoint = originPoint.add({x: 24, y: -24});
// 3) Convert back into LatLng.
var nextCornerLatLng = map.containerPointToLatLng(nextCornerPoint);
var imageOverlay = L.imageOverlay(
'path/to/image',
[originLatLng, nextCornerLatLng]
).addTo(map);
Demo: http://playground-leaflet.rhcloud.com/tehi/1/edit?html,output
Working example: http://markercluster.meteor.com/
If you double click on the map to add a marker, then this place will be the upper left corner marker, not pin.
The coordinates of the mouse pointer and marker coordinates coincide: it can be seen in the browser console.
Actually the question: What am I doing wrong? How to make a marker added correctly?
Solved by adding option iconAnchor
EDIT:
myIcon = L.icon(
iconUrl: "packages/leaflet/images/marker-icon.png"
shadowUrl: "packages/leaflet/images/marker-shadow.png"
iconAnchor: [12, 41] #[iconWidth/2, iconHeight]
)
I have a province boundary polygon in geojson format. What I want is to show this province on the map with the non-province area greyed out (opaque) and the province area shown without style. How can I achieve this?
From the Polygon api documentation:
You can also create a polygon with holes by passing an array of arrays of latlngs, with the first latlngs array representing the exterior ring while the remaining represent the holes inside.
So I think you can use that to make a really big polygon for the exterior ring, with the province cut out in as a hole inside. Of course, if you zoom to a level bigger than the big polygon, that's gonna look awkward. Perhaps best set a min zoom level so that this won't happen.
var polygon = L.polygon(
[[[52, -1],
[52, 1],
[50, 1],
[50, -1]], //outer ring
[[51.509, -0.08],
[51.503, -0.07],
[51.51, -0.047]]] // cutout
).addTo(map);
JSfiddle
Or set the outer polygon to cover the entire world:
[[90, -180],
[90, 180],
[-90, 180],
[-90, -180]]