Update Mapbox direction instructions while driving/walking + add direction indicator - geolocation

I'm building a web app to view featured walking routes in my neighbourhood.
User opens the app and sees all different routes.
App gets current location and checks for most nearby route.
App requests the route to one of my featured routes.
User can use the app to navigate to a marker from my featured route that is most nearby.
I'm working with the Directions Service which can give me a list of walking instructions like this:
I'm now trying to combine the directions with my current location. What is the best option to do this? I want to update the instructions based on my current location so for example if I head east on the Amstelkade I want to see the next instruction at the top. I came up with the following:
Add GeolocateControl to Mapbox
let geolocate = new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true
})
map.addControl(geolocate);
Put a listener on the geolocate change event and update starting place (origin) to get the latest direction instructions.
geolocate.on('geolocate', function(location) {
currentLocation = location;
setOrigin(location);
setDestination(location);
});
function setOrigin(location){
if(Object.keys(directions.getOrigin()).length === 0){
directions.setOrigin([location.coords.longitude, location.coords.latitude]);
}
}
I'm a little bit lost if this is a proper solution because in this way i'm making a lot of requests (could put a debouncer on the geolocate event though). Is there a better way to solve this and make it more user friendly?
Question 2: is it possible to add a direction indicator (blue beam of direction you're heading) to Mapbox like Google does?
Thanks all!

Related

Openlayers 3.6: Getting the center of the current map view

I'm trying to get the current center of an Openlayers map in lat/lon coordinates. I've got the following event handler setup:
this.map.on('pointermove', function (e) {
if (e.dragging) {
console.log(that.map.getView().getCenter());
}
});
This works, but I'm getting weird values. Here's an example:
[9318218.659044644, 3274618.6225819485]
Those are obviously not lat/lon values :) Do I need to transform this somehow? Thanks!
I'm not super familiar with openlayers but it sounds like the map is in different projection.
Check out the following on spherical_mercator, transform,
Open Layers projections
UPDATED
I've done a little more research, check out this example. Not sure what the projection your view is in. the map in this example is in ''EPSG:21781' if you go to a js console and enter map.getView().getCenter() you get [693230.7161150641, 179010.3389264635] but if you enter ol.proj.transform(map.getView().getCenter(), 'EPSG:21781', 'EPSG:4326') you get [8.658936030357363, 46.75575224283748] hope that helps.
For those who are working with angular.
Also, I would consider searching the projection of the map, instead of entering it manually.
import * as olProj from 'ol/proj'
import Map from 'ol/Map'
// ...
olProj.transform(
this.map.getView().getCenter(),
this.map.getView().getProjection(),
'EPSG:4326',
)
Update for OpenLayers 6 (assuming your map is called 'map') the following gives an array of [lon, lat] for the centre of your map's view.
ol.proj.toLonLat( map.getView().getCenter() )

Angularjs: linking to phone's mapping app

I have a webapp that wants to offload walking / driving directions to a phone's native apps. This would be Google Maps app and maps.apple.com for Android and iOS respectively. I can detect the phone from the user agent presumably, but I can't work out how to configure the link.
<li><a href ng-click="geoHandler()"> Directions</a></li>
This is what I have in the relevant controller.
$scope.geoHandler = function() {
// user agent sniffing here
var path = "geo:0,0?q="+$scope.resto.lat+","+$scope.resto.lng+"("+$scope.resto.rname+")";
// var path = http://maps.apple.com/?ll=$scope.resto.lat+","+$scope.resto.lng
return $location.path(path);
}
When I had the geo link as the href in the html, the phone did the right thing, but now this code is taking me simply to the home page of my SPA.
So, my questions are:
is ng-click the right way to go (I can't use a function with ng-href I think);
how do I launch an intent via $location?
OK, I moved to a different and simpler approach. Not sure whether it is the most elegant, but it works.
View
<a ng-href="{{geoPath}}">Directions</a>
Controller
if ( /iPhone/.test(navigator.userAgent))
path = "http://maps.apple.com/?ll="+$scope.resto.lat+","+$scope.resto.lng";
else path = "geo:0,0?q="+$scope.resto.lat+","+$scope.resto.lng+"("+$scope.resto.rname+")";
$scope.geoPath = path;

Implementing a search function for a marker

I have Markers setup with gmaps4rails.
Now I want to implement a classic search function.
If I find one object, it should directly show the marker.infowindow
How do I open it directly?
I tried:
function focusSearch() {
handler.map.centerOn({ lat: <%=#searchy.latitude %>, lng: <%=#searchy.longitude %>});
handler.getMap().setZoom(16);
marker = <%=#searchy.id%>
marker.infowindow.open(map, marker.serviceObject);
}
But I guess I am going wrong there...
Anyone can help?
If you have an Idea how to directly use the #search:params, I am happy!
Thanks for helping out!
I've created a plunkr with working code here.
Basically steps are:
associate the marker to the original json data where ids are available
search the marker list for the id you expect
trigger the 'click' google map event on the marker which triggers pan + infowindow

How to register map move / map pan events in OpenLayers 3

I'm looking for OpenLayer 3 map event for map move/map pan, something like:
map.on('move', function(){
...
}
Does anyone know how to implement?
The moveend event might be the one you search for - it detects any move made, even those not invoked by dragging.
map.on('moveend', function (e) {
console.log("moved");
});
See http://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html
UPDATE:
These events are no longer present in recent versions. Please refer to the more recent answer for an up-to-date information.
Names of the events you're looking for are drag and/or dragend (it's probably a better idea to depend on properties names, though: ol.MapBrowserEvent.EventType.DRAG but it didn't work on the demo page):
map.on('drag', function() {
console.log('Dragging...');
});
map.on('dragend', function() {
console.log('Dragging ended.');
});
Reverse-engineered by looking inside mapbrowserevent.js, the documentation explicitly mentions events are not documented yet.
MoveEnd trigger if u move the map with a script.
I have use that in OpenLayers 6:
map.on('pointerdrag', function (event) {
is_map_center = false;
})
hf gl!
I believe this functionality exists in 2 functions within the View of a map, not the map itself. You can monitor the center property of the View by listening for change:center events. There is also a getInteracting() method in ol.View that will return a boolean if an interaction (zooming or panning) is occurring.
https://openlayers.org/en/v4.6.5/apidoc/ol.View.html#getInteracting

Editing a BrowserField's History

I have a BrowserField in my app, which works great. It intercept NavigationRequests to links on my website which go to external sites, and brings up a new windows to display those in the regular Browser, which also works great.
The problem I have is that if a user clicks a link to say "www.google.com", my app opens that up in a new browser, but also logs it into the BrowserHistory. So if they click back, away from google, they arrive back at my app, but then if they hit back again, the BrowserHistory would land them on the same page they were on (Because going back from Google doesn't move back in the history) I've tried to find a way to edit the BrowserField's BrowserHistory, but this doesn't seem possible. Short of creating my own class for logging the browsing history, is there anything I can do?
If I didn't do a good job explaining the problem, don't hesitate for clarification.
Thanks
One possible solution to this problem would be to keep track of the last inner URL visited before the current NavigationRequest URL. You could then check to see whether the link clicked is an outside link, as you already do, and if it is call this method:
updateHistory(String url, boolean isRedirect)
with the last URL before the outside link. Using your example this should overwrite "www.google.com" with the last inner URL before the outside link was clicked.
Here is some half pseudocode/half Java to illustrate my solution:
BrowserFieldHistory history = browserField.getHistory():
String lastInnerURL = "";
if navigationRequest is an outside link {
history.updateHistory(lastInnerURL, true);
// Handle loading of outer website
} else {
lastInnerURL = navigationRequest;
// Visit inner navigation request as normal
}
http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/browser/field2/BrowserFieldHistory.html#updateHistory(java.lang.String, boolean)
I had a similar but a little bit different issue. Special links in html content like device:smth are used to open barcode scanner, logout etc and I wanted them not to be saved in BrowserFieldHistory. I found in WebWork source code interesting workaround for that. All that you need is throw exception at the end like below:
public void handleNavigationRequest( BrowserFieldRequest request ) throws Exception {
if scheme equals to device {
// perform logout, open barcode scanner, etc
throw new Exception(); // this exception prevent saving history
} else {
// standard behavior
}
}

Resources