I'm using HTML geolocation and I'd like to achieve the following:
1. User arrives at page
2. User is asked to share location
3. When user says yes, Google Maps initialises and centres on their position
4. We add marker to map showing their position
5. (ongoing) As the user moves, the marker continues to move with them
I've implemented this as follows:
// Add a marker
function addMarker(loc) { // adds marker }
function setupMap(loc) { // initialise map and centre on user's position };
setUpMap(???????);
// Start watching user's position
var watchID = navigator.geolocation.watchPosition(addMarker);
So my question is: how can I get the initial position in order to set up the map?
I can see two options, both of which have flaws:
Call setUpMap from within addMarker, but then the map gets re-initialised each time the user moves, which is obviously inefficient.
Call navigator.geolocation.getCurrentPosition before calling watchLocation - but then the user seems to get prompted twice for their location, which looks clunky.
Any better ideas?
Thanks everyone.
UPDATE
OK, it seems I haven't explained this well. My question is really: how do I get the user's location from watchPosition, as a one-off, so that I can initialise the map once?
Call this:
navigator.geolocation.watchPosition
instead of this:
navigator.geolocation.getCurrentPosition
watchPosition function also initializes positions.
3. Call watchLocation in step two, i.e. to get initial location (the user therefore will only get prompted once)
Related
I'm trying to draw polygon on my map using ngmap. The map is displayed correctly as this example is showing, but when I finish the draw, this is what I'm getting:
ng-map.min.js:25 Uncaught TypeError: Cannot read property 'onMapOverlayCompleted' of undefined
I used the same code of the example.
My questions:
1- How can I solve this error?
2- If I want to let the user draw only polygon form, I have tried to set the value of drawingMode to "polygon" but I'm always having the other draw options (circle...). How can let only the polygon draw?
3- How can I let the user clear the drawn polygon?
4- Is it possible to detect the action of putting (drawing) every points. I mean that to draw a line in the polygon for example I need at least two points. Can I detect when the user draw the first point then the second and get its coordinates?
Edit
This is the whole error that I see when I include ng-map.js instead of ng-map.min.js :
Uncaught TypeError: Cannot read property 'onMapOverlayCompleted' of undefined
at index (http://localhost:8080/bower_components/ngmap/build/scripts/ng-map.js:2690:44)
at Array.reduce (native)
at Uw.<anonymous> (http://localhost:8080/bower_components/ngmap/build/scripts/ng-map.js:2691:39)
at P4._.z.trigger (https://maps.google.com/maps/api/js?key=MY_API_KEY&libraries=placeses,visualization,drawing,geometry,places:99:121)
at P4.<anonymous> (https://maps.google.com/maps/api/js?key=MY_API_KEY&libraries=placeses,visualization,drawing,geometry,places:37:81)
at C4._.z.trigger (https://maps.google.com/maps/api/js?key=MY_API_KEY&libraries=placeses,visualization,drawing,geometry,places:99:121)
at C4.<anonymous> (https://maps.google.com/maps/api/js?key=MY_API_KEY&libraries=placeses,visualization,drawing,geometry,places:37:81)
at Object._.z.trigger (https://maps.google.com/maps/api/js?key=MY_API_KEY&libraries=placeses,visualization,drawing,geometry,places:99:121)
at F4 (https://maps.google.com/maps-api-v3/api/js/28/14/drawing_impl.js:7:70)
at G4 (https://maps.google.com/maps-api-v3/api/js/28/14/drawing_impl.js:4:249)
Edit 2
I solved the first question:
My problem was that I'm using routes in the app.js. So the html and the controller are linked in it. To solve the problem, I put $scope.onMapOverlayCompleted instead of
var vm = this;
vm.onMapOverlayCompleted because I don't write the the ng-controller="DrawingManagerCtrl as vm" in my HTML. Then in the HTML I put on-overlaycomplete="onMapOverlayCompleted()" and it works.
I solved also the second question by using:
drawing-control-options="{position: 'TOP_CENTER',drawingModes:['polygon']}"
I'm want now to solve the other problems.
Any help please?
3
As the example you referenced shows, the overlaycomplete callback function receives e (Event) as the first parameter. This OverlayCompleteEvent object contains reference to the drawn overlay at Event.overlay (see docs of the original Google Maps JS API more info, since ng-map is only wrapper of the original API after all, specifically "OverlayCompleteEvent object specification" section).
Using that you can get the reference to the created overlay, store it and then later call .setMap(null) on it to delete it from map. E.g:
$scope.myDrawnOverlays = []; //array where you store drawn overlays
$scope.onMapOverlayCompleted(e){
...
myDrawnOverlays.push(e.overlay); //store reference to the drawn overlay after it's drawn
}
$scope.deleteAllDrawnOverlays(){
for(var i = 0; i < myDrawnOverlays.length; i++){
myDrawnOverlays[i].setMap(null); //remove overlays from map one by one
}
myDrawnOverlays = [];
}
Then whenever you want to delete all overlays, just call the function $scope.deleteAllDrawnOverlays (you can tie it to some button using ng-click or do whatever you want with it).
4
This is NOT possible using google.maps.drawing.DrawingManager which is used in your example. The reason is that DrawingManager doesn't support events for clicking at the map while drawing (see docs again for possible events, section "DrawingManager class").
So except hacky workarounds which could break any time with new api release, the only possible solution is to implement drawing of polygon yourself and not use DrawingManager. Check for example this SO answer, specifically the referenced example (right-clicks on map). They don't use ng-map, but basically what would you have to do is to add on-click="mapClickHandler" to your ng-map, in the mapClickHandler get position where you clicked on map, draw Marker there which would look like a dot and if you have more dots connect them with lines.
This is however too much for one question, you would have to probably read up on ng-map and relevant sections of Google Maps Js Api yourself.
I'm making a marker for a google map in primefaces and I'd like to set the icon. But the constructor for marker that allows setting the icon requires a parameter called "data". I'm not finding data being documented anywhere although one place I found says that it gets passed to super(). I can work around this by using a different constructor and then making a call to setIcon but that's two steps instead of one. So, any idea of what data is and how to safely make the call to the constructor that sets the icon?
I haven't had much of an opportunity to look at HTML5 Geolocation yet, but I'm curious: Is it possible to build a web app that can detect when a user enters a certain area (perimeter) and then return a message or something like that?
You can use watchPosition to get periodic updates of the browser's location, and then in your callback, test to see if the new position is within your area of interest. So if you've defined a function isInArea that checks a position to see if it's in your area of interest, you could do something like:
function positionCallback(position) {
if (isInArea(position)) {
alert("Honey, I'm home!");
}
}
function handleError(error) {
alert("Error!")
}
// Request repeated updates.
var watchId = navigator.geolocation.watchPosition(positionCallback, handleError);
Based on Example of requesting repeated position updates from w3c.
I am having problems with centering the map using the panTo() method - as well as making the directions (from/to) to work like tabs.
Here is my code:
http://dpaste.com/76251/
I'm not too sure what you want the map to do, but there is one big problem with your panTo() function. You placed it inside of the function markerClickHandler() which is called when the markers are created, which happens on page load. So you are calling panTo() three times when the page is loaded.
If you want it to be called when the marker is clicked, place it in the function which is returned by markerClickHandler().
Keep in mind, however, that the movement will likely be interrupted by the opening of the Info Window (which moves the map). The best solution I can think of to that problem is to move the map after the window has opened. You can pass onOpenFn as a GInfoWindowOptions parameter:
map.openInfoWindowTabsHtml(marker.getLatLng(), tabs, {
onOpenFn: function() {
map.panTo(marker.getLatLng());
}
});
Note: for some reason, this only worked if I called openInfoWindowTabsHtml() on the map object instead of the marker - I don't know why.
The example snippet you're linking to is no longer available, but assuming from the answer by Chris, I'm assuming you want to center the marker whose info window was opened. I had the same problem and solved it like this:
GEvent.addListener(marker, 'infowindowopen', function() {
map.panTo(marker.getLatLng());
});
I've got a plain-vanilla google maps widget sitting in a page and I'd like it if the driving directions opened up in a new window instead of taking over the current window. Is there a setting for this?
The driving directions go into whatever HTML element you specify as the second argument when you construct the GDirections object. So I guess that means you'd have to create the window before you create the GDirections object, which is likely not what you want.
The other thing that jumps out, looking at the documentation, is that you can call the load() method with the option getSteps = true. It's not clear what the "steps" data looks like, but I assume it essentially comes back as an HTML string. (Actually, it's not even clear how you get the data in the first place, but I assume it's GDirections.getSteps() or something similar.) So then when the "load" event happens, you can create the new window then put the "steps" data in it.