How do I get all administrative divisions/boundaries along a route? - here-api

We're currently getting routes using the v8 endpoint seen at:
https://developer.here.com/documentation/routing-api/api-reference-swagger.html
For each route, we'd like to get all administrative divisions/regions/boundaries such as states, counties, cities, etc (for United States). How might we go about doing this?
We've thought about using HERE polylines in tandem with OpenStreetMap but I would hope that there might already be a solution for this?

you can use map tile api to to show map in the background as shown in this sample example : https://demo.support.here.com/examples/v3.1/simple_routing
(function(){
/*
author
(C) HERE 2019
*/
var mapContainer = document.getElementById('mapContainer');
// check if the site was loaded via secure connection
var secure = (location.protocol === 'https:') ? true : false;
var platform = new H.service.Platform({
useHTTPS: secure,
apikey: api_key
}),
defaultLayers = platform.createDefaultLayers(),
router = platform.getRoutingService(),
map = new H.Map(mapContainer, defaultLayers.vector.normal.map,
{
center: center,
zoom: zoom,
pixelRatio: window.devicePixelRatio || 1
}
);
// Do not draw under control panel
map.getViewPort().setPadding(0, 0, 0, $('.ctrl-panel').width());
// add behavior control
new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Enable the default UI
var ui = H.ui.UI.createDefault(map, defaultLayers);
window.addEventListener('resize', function() { map.getViewPort().resize(); });
function calculateRoute()
{
var calculateRouteParams = {
'waypoint0' : '52.516222,13.388900',
'waypoint1' : '52.517175,13.395129',
'mode': 'fastest;car;traffic:disabled',
'representation': 'display'
},
onResult = function(result) {
var lineString = new H.geo.LineString(),
routeShape = result.response.route[0].shape,
polyline;
routeShape.forEach(function(point) {
var parts = point.split(',');
lineString.pushLatLngAlt(parts[0], parts[1]);
});
var polyline = new H.map.Polyline(lineString,
{
style:
{
lineWidth: 10,
strokeColor: "rgba(0, 128, 0, 0.7)"
}
});
map.addObject(polyline);
map.getViewModel().setLookAtData({
tilt: 45,
bounds: polyline.getBoundingBox()
});
},
onError = function(error) {
console.log(error);
}
router.calculateRoute(calculateRouteParams, onResult, onError);
}
var displayReady = function(e)
{
map.removeEventListener("mapviewchangeend", displayReady);
calculateRoute();
};
map.addEventListener("mapviewchangeend", displayReady);
})

Related

How to show dynamically multiple popup in openlayers 3 map

Can anyone tell me how to show all popup of markers in openlayers 3 map. I searched many sites but couldn't get any answer please anyone know about this then help me
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.TileJSON({
url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure',
crossOrigin: 'anonymous'
})
})
],
overlays: [overlay],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([0, 50]),
zoom: 2
})
});
var vectorSource = new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([16.37, 48.2])),
name: 'London'
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-0.13, 51.51])),
name: 'NY'
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([30.69, 55.21])),
name: 'Paris'
})
]
});
var markers = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
image: new ol.style.Icon({
src: '//openlayers.org/en/v3.12.1/examples/data/icon.png',
anchor: [0.5, 1]
})
})
});
map.addLayer(markers);
function showpopup(){
// For showing popups on Map
var arrayData = [1];
showInfoOnMap(map,arrayData,1);
function showInfoOnMap(map, arrayData, flag) {
var flag = 'show';
var extent = map.getView().calculateExtent(map.getSize());
var id = 0;
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
positioning: 'center'
});
map.addOverlay(popup);
if (arrayData != null && arrayData.length > 0) {
arrayData.forEach(function(vectorSource) {
/* logMessage('vectorSource >> ' + vectorSource); */
if (vectorSource != null && markers.getSource().getFeatures() != null && markers.getSource().getFeatures().length > 0) {
markers.getSource().forEachFeatureInExtent(extent, function(feature) {
/* logMessage('vectorSource feature >> ' + feature); */
console.log("vectorSource feature >> " + markers.getSource().getFeatures());
if (flag == 'show') {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
popup.setPosition(coord);
/* var prop;
var vyprop = ""; */
$(element).popover({
'position': 'center',
'placement': 'top',
'template':'<div class="popover"><div class="popover-content"></div></div>',
'html': true,
'content': function() {
var string = [];
var st = feature.U.name;
if (st != null && st.length > 0) {
var arrayLength = 1;
string = "<table>";
string += '<tr><td>' + st + "</table>";
}
return string;
}
});
$(element).popover('show');
} else {
$(element).popover('destroy');
}
});
}
});
}
};
}
I used this code in my file but it show only one popup on all markers please someone tell me how to show all markers popup simultaneously.
I'm not sure exactly what you're trying to show in your popups, but I would probably try this approach. This extends the ol.Overlay class, allowing you to get the map object and attach a listener which you can use to grab the feature that was clicked. Is this what you're trying to accomplish?
function PopupOverlay() {
var element = document.createElement('div');
$(element).popover({
template: '<div class="popover"><div class="popover-content"></div></div>',
placement: 'top',
position: 'center',
html: true
});
ol.Overlay.call(this, {
element: element
});
}
ol.inherits(PopupOverlay, ol.Overlay);
PopupOverlay.prototype.setMap = function (map) {
var self = this;
map.on('singleclick', function (e) {
map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
ol.Overlay.prototype.setPosition.call(self, feature.getGeometry().getCoordinates());
var el = self.getElement();
$(el).data('bs.popover').options.content = function () {
// EDIT THE POPOVER CONTENT
return feature.get('name');
};
$(el).popover('show');
});
});
ol.Overlay.prototype.setMap.call(this, map);
};
Check out this example
So after your comment, I see what you're trying to do now. I would say that you want to take the same basic approach, make a class that overrides ol.Overlay, but this time just loop through all the features, creating an overlay for each feature.
This Updated Example
function PopoverOverlay(feature, map) {
this.feature = feature;
var element = document.createElement('div');
$(element).popover({
template: '<div class="popover"><div class="popover-content"></div></div>',
placement: 'top',
position: 'center',
html: true
});
ol.Overlay.call(this, {
element: element,
map: map
});
};
ol.inherits(PopoverOverlay, ol.Overlay);
PopoverOverlay.prototype.togglePopover = function () {
ol.Overlay.prototype.setPosition.call(this, this.feature.getGeometry().getCoordinates());
var self = this;
var el = this.getElement();
$(el).data('bs.popover').options.content = function () {
// EDIT THE POPOVER CONTENT
return self.feature.get('name');
};
$(el).popover('toggle');
};
// create overlays for each feature
var overlays = (function createOverlays () {
var popupOverlays = [];
vectorSource.getFeatures().forEach(function (feature) {
var overlay = new PopoverOverlay(feature, map);
popupOverlays.push(overlay);
map.addOverlay(overlay);
});
return popupOverlays;
})();
// on click, toggle the popovers
map.on('singleclick', function () {
for(var i in overlays) {
overlays[i].togglePopover();
}
});
Now when you click anywhere on the map, it should call the togglePopover method and toggle the popover on the individual element.

Google Map: Link to the map according to feature type

I have a google Map with markers on a webpage.
Each marker has a unique feature position and type
This is the scenario I would like to put in place:
On another webpage I have static links to different markers of the map.
If you click on one of those links, you are directed to the map in which, one of these markers is centered (and its info window open).
But the markers latitude and longitude might change while the links will never change.
This means, I need the links not to use latitude and longitude info but markers feature type instead (which are remain the same).
How can I do that?
Here is my sample google Map script so far:
<script>
function initMap() {
var mapDiv = document.getElementById('map');
var map = new google.maps.Map(mapDiv, {
center: {lat: 48.85639, lng: 2.33625}, // default centering
zoom: 18,
styles:
[
{featureType: 'poi',stylers: [{ visibility: 'off' }]},
{featureType: 'transit.station',stylers: [{ visibility: "off" }]}
]
});
var features = [
{position: new google.maps.LatLng(48.85659, 2.33555),type: 'markerone'},
{position: new google.maps.LatLng(48.85619, 2.33695),type: 'markertwo'}
];
var icons = {
'markerone': {icon: 'icon_one.png'},
'markertwo': {icon: 'icon_two.png'}
};
var contents= {
'markerone': {text: 'Content 1'},
'markertwo': {text: 'Content 2'}
};
for (var i = 0, feature; feature = features[i]; i++)
{
var marker = new google.maps.Marker({
position: feature.position,
icon: icons[feature.type].icon,
map: map
});
var content = contents[feature.type].text;
var infowindow = new google.maps.InfoWindow()
google.maps.event.addListener(marker,'mouseover', (function(marker,content,infowindow){
return function() {
infowindow.setContent(content);
infowindow.open(map,marker);
};
})(marker,content,infowindow));
google.maps.event.addListener(marker,'mouseout', (function(marker,content,infowindow){
return function() {
infowindow.close(map,marker);
};
})(marker,content,infowindow));
}
}
</script>
In this sample, I have to markers.
One has a feature type of "markerone" and the second is "markertwo".
How can I set my links to redirect and center the map around a specific marker in this kind of fashion:
http://www.mywebsite.com/mymap.php?myvariable=markertwo
Thank you.
First you would have to get the parameters. The example below gets all parameters and put them into an array. There you can search for your certain paramater like "markerType" and check if it's given or not. If not you have to perform a default action, otherwise you can handle the certain markerType like finding the correct marker, setting the map center to it and open the corrosponding infoWindow.
You just have to call the focusMarkerType-method onload of your page.
function getSearchParameters() {
var prmstr = window.location.search.substr(1);
return prmstr != null && prmstr != "" ? transformToAssocArray(prmstr) : {};
}
function transformToAssocArray( prmstr ) {
var params = {};
var prmarr = prmstr.split("&");
for ( var i = 0; i < prmarr.length; i++) {
var tmparr = prmarr[i].split("=");
params[tmparr[0]] = tmparr[1];
}
return params;
}
function focusMarkerType(){
var params = getSearchParameters();
if(params.markerType!=null){
//Handling the certain marker type
var found = false;
for (var i = 0, feature; feature = features[i]; i++) {
if (feature.type == params.markerType) {
found = true;
map.setCenter(feature.position);
//more...
break;
}
}
if (!found) {
console.log("unknown type")
}
}else{
//Handling default behaviour if no marker type is given
}
}

Google Maps API Marker Clusterer and Ajax

I am running multiple ajax calls to download a large number of google maps icons. When I try to increment the Marker Clusterer, however, the map clears all markers. I believe this is because I am calling var markerCluster = new MarkerCluster(map); in each AJAX call.
Can anyone tell me how to correctly implement this?
var populateMapByIncident = function(incident, page) {
var run_again = false;
$.getJSON(
"/public_map_ajax_handler",
{"shortname" : incident, "page": page},
function(sites_list) {
if (sites_list.length > 2) {
run_again = true;
}
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(40.6501038, -73.8495823),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var markers = [];
var i = 0;
for (var i = 0; i < sites_list.length; i++) {
var latLng = new google.maps.LatLng(sites_list[i].latitude, sites_list[i].longitude);
var marker = new google.maps.Marker({'position': latLng,
'icon': getMarkerIcon(sites_list[i]),
'site_id': sites_list[i].id,
'case_number': sites_list[i].case_number,
'work_type': sites_list[i].work_type,
'floors_affected': sites_list[i].floors_affected,
'status': sites_list[i].status});
markers.push(marker);
var site_id = sites_list[i].id;
google.maps.event.addListener(marker, "click", function() {
new Messi('<p>Name, Address, Phone Number are removed from the public map</p><p>Details: work type: '
+ this.work_type+ ', floors affected: ' + this.floors_affected + '</p>' + '<p>Status: ' + this.status + '</p>',
{title: 'Case Number: ' + this.case_number, titleClass: 'info',
buttons: [
{id: 0, label: 'Printer Friendly', val: "On the live version, this would send all of this site's data to a printer friendly page." },
{id: 1, label: 'Change Status', val: "On the live version, you would be able to change the site's status here."},
{id: 2, label: 'Edit', val: "On the live version, you would be able to edit the site's info, as new details come in."},
{id: 3, label: 'Claim', val: "On the live version, clicking this button would 'Claim' the site for your organization, letting other organizations know that you intend to work on that site"},
{id: 4, label: 'Close', val: 'None'}], callback: function(val) { if (val != "None") {Messi.alert(val);} }});
});
}
var markerCluster = new MarkerClusterer(map);
markerCluster.addMarkers(markers);
if (run_again == true) {
populateMapByIncident(incident, page + 1, markers);
} else {
markerCluster.addMarkers(markers);
}
}
);
}
I am running multiple ajax calls to download a large number of google maps icons. When I try to increment the Marker Clusterer, however, the map clears all markers. I believe this is because I am calling var markerCluster = new MarkerCluster(map); in each AJAX call.
Can anyone tell me how to correctly implement this?
Don't do that. Create the MarkerClusterer one time in the global scope (outside of any function), and add markers to it when you receive them from the server (assuming you aren't sending any duplicates).
See the documentation
Looks like you are already adding arrays of markers to the MarkerClusterer:
addMarkers(markers:Array., opt_nodraw:boolean) | None | Add an array of markers to the clusterer.
All you really need to do is move where you create the MarkerClusterer to the global scope. One suggestion below.
var markerCluster = new MarkerClusterer(map); // <------------- add this
var populateMapByIncident = function(incident, page) {
var run_again = false;
$.getJSON(
// ----- existing code ------- //
// leave as is
// ----- modification -------- //
// var markerCluster = new MarkerClusterer(map); <----------- remove this
markerCluster.addMarkers(markers);
if (run_again == true) {
populateMapByIncident(incident, page + 1, markers);
} else {
markerCluster.addMarkers(markers);
}

Initializing Google Maps as an AMD module

To initialize google.maps as an AMD module, compliant with twitter/flight and requirejs, use:
define([
'components/flight/lib/component',
'async!http://maps.google.com/maps/api/js?key=AIzaSyDp9D9Db1CWfeGUJ1bin45s2WKZN5sapuM&sensor=false'
], function(defineComponent){
return defineComponent(newMap);
function newMap () {
this.defaultAttrs({
// Selector
mapDiv: '#map',
// Map Canvas
mapCanvas: {},
// Initialized?
initializedMap: false
});
this.initializeMap = function () {
var mapCenter = new google.maps.LatLng(39.960664,-75.605488);
var mapOptions = {
zoom: 15,
center: mapCenter,
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
this.attr.mapCanvas = new google.maps.Map(document.getElementById("map"), mapOptions);
if (this.attr.mapCanvas != {} ) {
this.attr.initializedMap = true;
this.trigger(document, 'mapInitialized', {
status: this.attr.initializedMap
});
};
// ### Map events
//-----------
// Mouse Up
google.maps.event.addListener(this.attr.mapCanvas, 'mouseup', function() {
this.trigger('mouseup');
});
// Zoom Changed
google.maps.event.addListener(this.attr.mapCanvas, 'zoom_changed', function() {
this.trigger('zoomChanged');
});
};
this.mouseup = function () {
console.log("what");
}
this.zoomChanged = function () {
console.log("is up");
}
this.after('initialize', function () {
this.on('mouseup', this.mouseup);
this.on('zoomChanged', this.zoomChanged);
this.on('initializeMap', this.initializeMap);
this.trigger('initializeMap');
});
}
});
I put together a Google Maps AMD loader plugin, which adds some functionality on top of the async! loader.
require.config({
googlemaps: {
params: {
key: 'abcd1234', // sets api key
libraries: 'geometry' // set google libraries
}
}
});
require(['googlemaps!'], function(gmaps) {
// google.maps available as gmaps
var map = new gmaps.Map('map-canvas');
});

Google Maps API with backbone, how to bind an event

I've seen several other posts about this, but the answers from those responses don't work for me.
The other responses:
How do I bind a google maps geocoder.geocode() callback function
Backbone.js with Google Maps - problems with this and listeners
My code:
var ns = namespace('camelcase.geomanager.map');
ns.Site = Backbone.Model.extend({
url: '/site'
});
ns.Sites = Backbone.Collection.extend({
model: ns.Site
});
ns.MapView = Backbone.View.extend({
initialize: function() {
this.markers = new Array();
// Create the Google Map
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.googleMap = new google.maps.Map(this.$(".mapCanvas")[0], mapOptions);
// Register events
this.collection.on('add', this.addSite, this);
this.collection.on('remove', this.removeSite, this);
},
addSite: function(model) {
// Get model attributes
var elementId = model.get('elementId');
var latitude = model.get('latitude');
var longitude = model.get('longitude');
var id = model.get('id');
var notes = model.get('notes');
var title = ""+id;
// Create icon and marker
var icon = '/resources/img/elements/' + elementId + '_marker.png';
var latLng = new google.maps.LatLng(latitude, longitude);
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: this.googleMap,
icon: icon
});
// Load info window
var siteBubbleTemplate = _.template($('#siteBubbleTemplate').html());
var siteContent = $(siteBubbleTemplate({
siteId: id,
siteNotes: notes
}))[0];
var infoWindow = new google.maps.InfoWindow({
content: siteContent
});
// Show info window when clicking on marker
_.bindAll(this, this.openSite);
google.maps.event.addListener(marker, 'click', this.openSite(id));
this.markers.push({
id: id,
marker: marker,
infoWindow: infoWindow
});
},
openSite: function(id) {
var marker;
for (var c=0; c<this.markers.length; c++) {
marker = this.markers[c];
// Open the appropriate marker info window
if (marker.id == id) {
marker.infoWindow.open(googleMap, marker.marker);
}
// Close the rest
else {
marker.infoWindow.close();
}
}
}
});
The offending line:
google.maps.event.addListener(marker, 'click', this.openSite(id));
The error being reported in firebug:
TypeError: func is undefined
underscore.js (line 482)
I suspect this.marker is the problem, since you should be able to just refer to it by name.
google.maps.event.addListener(marker, 'click', this.openSite(id));
Looks like it was a scoping issue. I solved my problem with the following code:
// Show info window when clicking on marker
_.bindAll(this);
var _self = this;
var doSomething = function(event) {
_self.openSite({
event: event
});
};
google.maps.event.addListener(marker, 'click', doSomething);
I'll give the answer to whoever can best explain why this works.
In a model/collection event handler, Backbone sets 'this' to the model/collection which raised the event. If you call _.bindAll(this) in your view's initialize(), 'this' will be set to the view in your event handlers. Check out this jsfiddle: http://jsfiddle.net/9cvVv/339/ and see what happens when you uncomment _.bindAll(this);
var MyView = Backbone.View.extend({
initialize: function() {
// TODO: uncomment this line
// _.bindAll(this);
this.collection.bind('myEvent', this.onDoSomething);
},
updateCollection: function() {
this.collection.doSomething();
},
onDoSomething: function() {
if (this.models && typeof this.models.length === 'number') {
alert('"this" is a collection.');
}
else if (this.collection) {
alert('"this" is the view.');
}
else {
alert('"this" is something else.');
}
}
});

Resources