I have a map in leafletJS and when the icon moves along, I have the angle and I am using the Leaflet.RotatedMarker plugin to rotate the icon to face where its heading.
Does leaflet js have a plugin that can enable me to not supply the angle myself ...
L.marker([48.8631169, 2.3708919], {
rotationAngle: 45
}).addTo(map);
...and instead use a function like gogle maps' computeheading() ?
Edit:
Does mapbox have a function like computeHeading
https://github.com/bbecquet/Leaflet.RotatedMarker
js:
var boat_marker = L.marker([set_lat, set_long], {
pid: guid(),
// rotationAngle: 45,
icon: boatIcon,
draggable: true,
}).addTo(mymap);
function rotated_point() {
boat_marker.setRotationAngle(90);
}
No.
Leaflet has only a minimal set of geodesy-related functions. Functions to calculate headings, azymuths, geodesic distances or great circles are not needed for basic Leaflet functionality, and are not included.
A popular approach to this kind of problems is to rely on the javascript bindings of geographiclib for geodesy-related calculations (such as heading/azymuth), in the same way turf.js helps with geoprocessing of vector data.
Note that geographiclib is not a Leaflet plugin, but rather a generic set of geodesic functions. You will need to use a bit of care to get the latitude and longitude components of L.LatLngs, and fetch only the azymuth (and drop the distance) from the solution to the geodesic problem.
Related
I'm working on leaflet Js in which I expect user inputs of coordinates in X, Y form. i.e. Ghana meter Grid and I need to convert the X, Y into latitudes, and longitudes so that they can be plotted as markers on leaflet Js.
Since you are working with Javascript, I suggest to approach this problem with proj4js (the Javascript implementation of OSGeo's proj, the industry standard for converting coordinates between coordinate reference systems).
First, grab a release of proj4js, or use a CDN-hosted release, e.g.:
<script src='https://unpkg.com/proj4#2.6.2/dist/proj4.js'></script>
Proj4js doesn't come with the full definition list of CRSs (Coordinate Reference Systems), so you'll have to define the CRSs you want to work with. In your case, it's gonna be EPSG:25000 AKA "Ghana Metre Grid" and EPSG:4326 AKA "Equirectangular WGS84" AKA "latitude-longitude":
proj4.defs("EPSG:4326","+proj=longlat +datum=WGS84 +no_defs");
proj4.defs("EPSG:25000","+proj=tmerc +lat_0=4.666666666666667 +lon_0=-1 +k=0.99975 +x_0=274319.51 +y_0=0 +ellps=clrk80 +towgs84=-130,29,364,0,0,0,0 +units=m +no_defs");
You can fing the PROJ definitions of CRSs in either the data files of a PROJ release, or websites such as epsg.io.
Once the CRSs have been defined, call proj4js with their names and the coordinates to transform, e.g. to transform from EPSG:4326 to EPSG:25000...
console.log( proj4("EPSG:4326", "EPSG:25000", [-0.187, 5.6037]) );
...or from EPSG:25000 to EPSG:4326...
console.log( proj4("EPSG:25000", "EPSG:4326", [364346.57, 103339.95]) );
See a working example here.
Be wary of the order of coordinates (lat-lon vs lon-lat, or x-y vs y-x). Leaflet uses lat-lng, but proj uses x-y and lng-lat, so you'll have to flip the coordinates, e.g.
var accraLngLat = proj4("EPSG:25000", "EPSG:4326", [364346.57, 103339.95]);
L.marker([accraLngLat[1], accraLngLat[0]]).addTo(map);
or
var accraLngLat = proj4("EPSG:25000", "EPSG:4326", [364346.57, 103339.95]);
var accraLatLng = L.GeoJSON.coordsToLatLng(accraLngLat);
L.marker(accraLatLng).addTo(map);
See a working example here.
Also note that proj4js does all the reprojection work and there are no API calls involved.
Since you are specifically working with Leaflet, you might also be interested in proj4leaflet, although you might not need it. It'll be useful if you want to use Leaflet to display raster data (or map tiles) in different projections.
You can use this online converter: http://epsg.io/?q=Ghana
Using API parameters, you may be able to perform a GET request when the user inputs coordinates for conversion via your app.
With Mapbox GL JS, I can get a center and zoom level to show all of a given bounding box using the cameraForBounds method:
const {center, zoom} = map.cameraForBounds(
[
[sw.lng, sw.lat],
[ne.lng, ne.lat],
],
{
padding: 20,
bearing,
pitch, // probably ignored?
},
);
(The typings say that pitch is OK but the docs don't mention it and neither does the implementation, so I assume it's ignored.)
This usually works great, but there occasionally situations where I want to figure out the center/zoom before the map is initialized. It seems like the bounds → camera transformation should just be math, not requiring a Map instance.
How can I go from bounds and bearing (and ideally pitch) to a center/zoom that will include those bounds without an instance of a Mapbox GL map?
You can't, for the simple reason that you don't know how many pixels this map will occupy. Setting a centre and zoom determines how much area (and which area) will be covered by each pixel in the middle of the map. The bigger the map DOM element is, the more area will be covered by the area within the map.
I have a map for my Pen and Paper RPG and I want to show it via Leaflet.
I put the Png-File throw a Tile- Making Script and was able to generate this map.
I want to do the following things but don't know how:
Place the equator on the actual equator of the map
Putting bounds on the map, but only for the north-south-axis
The scale calculates with the dimensions of the real earth and i want to give it the dimensions of my world
I want my markers and polygons to repeat every 360°
I would appreciate any help,
Civer
To get the equator you could use a polyline like
var latlngs = [
[0, -180],
[0, 180]
];
var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
Not really sure what you mean by "putting bounds on the map". Are you saying you want to limit the user's ability to pan to areas outside of the map? Or are you talking about some sort of visual bounding line?
To do stuff with with different scales I'd suggest you look into how leaflet's Coordinate Reference System works (CRS). Take a look at this page: https://leafletjs.com/examples/crs-simple/crs-simple.html
It looks like you commented out some CRS stuff in your demo.
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);" />'})});"
Is it possible with leaflet.js or mapbox.js to determine what terrain / map type a marker is on.. For example the sea, land, road or buildings?
http://leafletjs.com/
http://mapbox.com/
If you are building your own map with TileMill, you could do this with interactivity: http://mapbox.com/tilemill/docs/crashcourse/tooltips/ You wouldn't necessary have to have a popup appear, but could instead use UTFGrid as a key/value store to indicate areas tapped on the map.
This is not a method provided in the LeafletJS package (that I know of).
However, you can combine your Leaflet map with the Google Geocoding API to return the location_type, which will tell you what type of terrain feature you're over.
It's not perfect but should give you the level of detail you're looking for.
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?latlng=' + marker._latlng.lat + ',' + marker._latlng.lng + '&sensor=false', function(data) {
var terrain = data.results[0].geometry.location_type;
});
Here's a jsFiddle showing how this could work.