Get coordinates of screen point on the map - javascript

I'm using a MapBox GL map in my web application. It has some interactivity features that I handle through pointermove events. When the user moves the pointer over the map (it might also be outside the map, which has different functionality) I can show a custom marker element (simple <div>, position is absolute to the document) over the map where the pointer currently is. When the drag operation is completed, I need to know the map coordinates under that point.
So what I need is a method to convert a screen or document position (X, Y) to the coordinates (Lat, Lng) on the map in its current view state.
All I found was the getCenter method that gives me the center of the map (not the pointer positition) or the project method that seems to do the exact opposite of what I need. There also seems to be the map's "mousemove" event or similar, which could give me the coordinates in the event data, but I'm not using that event, because the drag operation could have started outside the map. Seems I need the reverse operation of the project method. Is there any?

After digging through the map's source code regarding the "mousemove" event, I found the Map.unproject method. It seems to be what I need. It wants x/y coordinates relative to the map element, not the document though. I just didn't find it and Google didn't know what I mean either. Maybe this answer teaches Google a bit more about possible search terms not mentioned elsewhere.

Related

Is it possible to simultaneously use both the center and bounds attributes in Leaflet.js?

I have an web application, written using Angular.js and angular-leaflet-directive, that displays a selection of roads on a map. I have included some bookmarks for easy navigation to certain areas and so was basing map extent navigation on using the center and zoom attributes.
I am now also including functionality to determine whether a road is visible in the current map extent, using:
map.getBounds().contains([roadLatA, roadLngA]) || map.getBounds().contains([roadLatB, roadLngB]), where A and B refer to the end points of a road.
This works perfectly on page load but after any sort of interaction (e.g. drag, zoom events) when getBounds() is called again, it returns the same LatLng for each corner of the bounding box, which are the values that are set as the default center coordinates. After a lot of refactoring I cannot find a way to incorporate both center and getBounds() successfully.
Is it possible or is there a limitation within either angular-leaflet-directive or leaflet.js that means the two methods of setting map extent conflict with each other?
I have now resolved the problem, the issue was in calling leafletData.getMap() without passing in the id of the map element.
This behaviour was throwing me as the initial getMap() call (without an id) was returning the correct map object, but on subsequent calls (after user interaction) the $promise was not being resolved and so I wasn't getting undefined or any other errors. I guess the getBounds() function was then being called on the wrong map object.

Google Maps "cropping"

Okay so this may sound like a crazy question, but I have a Google Map (API v3) on a website, and at times I have a large number of markers on the map. Are there any plugins that exist, or how difficult would it be to write one, (starter code?) that would allow me to let the user say hit contrl + left mouse click and hold and enable them to "select" a portion of the map. After which when they release the left mouse button, I could fire an off a function that could update my google map to reset the zoom and only include the markers within the users selection area.
I'm really really wanting to try this, does anyone have any pointers or ideas that could help me?
UPDATE
Okay, is it even possible? :)
I believe it is possible however I think there is a better way to solve your problem which is to use clustering.
For the cropping you could:
Use event addDomListener to listen for 'mousedown' on the map. Check the event object passed to the handler to see if the ctrl key is pressed (e.ctrlKey).
Convert the x y coordinates for the mouse click into a lat lng (use fromPointToLatLng on the map projection). Create a rectangle at the position.
Add a addDomListener mousemove handler on the map. In the handler resize the rectangle using setBounds.
Add a addDomListener mouseup handler on the map. In the handler grab the bounds of the rectangle, remove the rectangle and call map.fitBounds.
I haven't tried the above but after all that typing I would recommend trying out clustering first to see if it satisfies your needs.

Reset Leaflet Map Choropleth on Zoom in and put it back on zoom out

Not sure if anyone is familiar with this leaflet map on the leaflet site found here:
http://leafletjs.com/examples/choropleth.html
It is a really cool map, just one thing. Is there a way to get the choropleth to disappear upon a certain zoom level? I know you can use map.getZoom() to detect zoom level. Essentially, I am trying to reset the styles that are invoked on page load within the function getColor(d).
Not sure how though. Any ideas?
Thanks in advance.
L.geoJson(statesData) returns an object with the method removeLayer. If you pass that object to a variable (let's just call it data) and call an anonymous function on zoomend you can capture the map's zoom level with map.getZoom(), you can match it to any arbitrary zoom level and then call data.removeLayer().
If you open up dev tools (aka your web inspector) in your browser and input the following line into your JavaScript console, you'll be able to see more methods and information that's fired whenever you zoom in and out of the map.
map.on('zoomend', function(e) { console.log(e); })

Zoom map out to contain the given map bounds

I have a google map app and the user is able to perform a marker search.
The search has the current mapBounds so that I can search only in the current view. However, if I don't have any results in the current view - I'm trying to do a search within 100km of the center of the map.
If I find location within 100km I want to zoom out the map in order to show the locations I've found.
On the server I go through all my locations and get the sw and ne points. So basically in my ajax response I can directly create latLngBounds (no need to loop through the markers locations and extend the bounds).
The issue is whenever I try to do map.fitBounds(mynewbounds); nothing happens. The map stays as it is.
It seems that since the center of the map is the center of the new bounds, the map doesn't want to move. If I do map.pantobounds then the map moves to the northwest corner of the bounds.
The behavior of pantoBounds is expected according to the documentation:
https://developers.google.com/maps/documentation/javascript/reference
If the bounds is larger than the map, the map will be shifted to include the northwest corner of the bounds
Any ideas how to make the map zoom out in order to contain the new bounds?
Okay, I just figured out what is going on. Right before I set the boundaries I was trying to remove my zoom_out and dragend events. Unfortunately I opted in for using the clearListeners event, which was removing all events set on the map (even the one that are not set by me). So it seems that fitBounds issues are zoom_changed event, but the map was not responding to it, as all listeners were removed.
Once I removed the correct events by using removeListener(listenerInstance) the fitBounds function started to behave as expected.
So just as a warning to everyone else! Don't use clearListeners if you don't know what you are doing. It removes all events assigned to the map object which can lead to nasty behavior!

Custom InfoWindow size/pointer position in Google Maps API

I have a map application that can be seen here:
http://chrismcaleenan.com/map/?page_id=25
Each of the Malaysian states in the application will have an InfoWindow that displays additional information. You can see an example of this by mousing over 'Kedah' either in the main data table on the right or on the state itself in the map.
The problem, as you can see, is that the map pans in order to position the InfoWindow. Is there a way to fix the map position and set the InfoWindow size or position so that it is fully displayed without panning? In the Kedah example, one could have the InfoWindow positioned directly to the right and/or use a shorter tail.
One option would be to create a custom graphic for each state, but I'd rather avoid this as I will be running into the same issue with add'l data (e.g. click Kedah to zoom - will have InfoWindows on all data points on zoom).
If you're playing around double-clicking the water will zoom back out and reset map.
Thanks!
Yes, and sometimes the pan pulls the mouse outside of the state, which causes the InfoWindow to disappear. I know that's not what you want. The Google Maps demo catalog includes a sample that I think will give you what you want for your map. It's named SmartInfoWindow. Take a look, click on some of the markers, check out how the SmartInfoWindow behaves, and see if that might help you achieve what you want. It's not perfect, but it keeps the pan at the absolute minimum.

Categories