google Maps: $.goMap() with custom overlayMapType - javascript

First: I try to remake a Website called regionalkarten.com
It's a German publisher of Maps. This page uses the Google API v2 to show our custom maps.
My Job is to update the Page to API v3.
Now I found the jQuery GoMap Plugin and I try to use it, but it doesn't seem to support custom maps.
I tried to define a Overly with the custom Map
var ehsTypeBOptions =
{
getTileUrl: function(coord, zoom)
{
var x = coord.x;
var y = coord.y;
return "http://regionalkarten.com/_map/ehs_village_maps/is_maps/z"+zoom+"/"+coord.y+"/"+coord.x+".png";
},
tileSize: new google.maps.Size(256, 256),
};
and load it into the map with:
map.overlayMapTypes.insertAt(0, new google.maps.ImageMapType(ehsTypeBOptions));
That works fine without GoMap. So I tried:
$.goMap.overlayMapTypes.insertAt(0, new google.maps.ImageMapType(ehsTypeBOptions));
and guess what, it didn't work :(
GoMaps Webpage and Google aren't very helpful. Keep in mind that I have to load the custom map into an overlay. I need the real google maps behind the overlay because our maps are not gapless.
I hope you got some ideas or experience with GoMap.
Thank you.

$.goMap does not return the native google.maps.Map-instance, so you can't use the Maps-API-methods there.
The google.maps.Map-instance may be accessed via $.goMap.map .
Beyond that: I would suggest not to use this library, there haven't been any updates since 1 year, and this all can be done without any additional library.
More important: before you continue working with ImageMapType, this is not the right MapType for you, because it appears that the TileServer don't serve tiles for the complete world.
When the user pans or zooms so that a area is in viewport where no tile is available, this area would be shown as a gray space. You better use a Overlay MapType and set the background-image of the overlays to the TileUrl(additionally you may use a condition that checks if a Tile is available at all to reduce unnecessary request to the tile-server)

Related

HERE Traffic incidents integration in Leaflet.js

Background:
I'm currently integrating HERE maps into our web-based application. I'm trying both - HERE provided Javascript API and Leaflet at the same time to find the best approach for our use-case.
While JavaScript API provided by HERE maps is OK, rendering wise Leaflet performs much better when using raster tiles.
Issue:
It would be fine by me to use raster tiles + leaflet, but our application also needs to display traffic incidents data.
Traffic incident data is provided by HERE in JSON and XML formats (Documentation link, Example JSON). They provide [Z]/[X]/[Y], quadkey, prox, bbox, or corridor filters which can be used to retrieve filtered data set.
I've tried using [Z]/[X]/[Y] addressing with custom L.TileLayer implementation which loads appropriate JSON, converts it to GeoJSON and displays GeoJSON on map. However that approach is very inefficient and significant performance drop is visible.
Question:
Maybe anyone has already solved this issue and could share any insights on how the HERE traffic incidents could be shown on Leaflet map without encountering performance issues?
I created the following script, which works without any performance issues:
var fg = L.featureGroup().addTo(map);
function loadTraffic(data) {
fg.clearLayers();
var d = data.TRAFFICITEMS.TRAFFICITEM.map((r) => {
var latlngs = [];
if (r.LOCATION.GEOLOC) {
if (r.LOCATION.GEOLOC.ORIGIN) {
latlngs.push(L.latLng(r.LOCATION.GEOLOC.ORIGIN.LATITUDE, r.LOCATION.GEOLOC.ORIGIN.LONGITUDE));
}
if (r.LOCATION.GEOLOC.TO) {
if (L.Util.isArray(r.LOCATION.GEOLOC.TO)) {
r.LOCATION.GEOLOC.TO.forEach((latlng) => {
latlngs.push(L.latLng(latlng.LATITUDE, latlng.LONGITUDE));
})
} else {
latlngs.push(L.latLng(r.LOCATION.GEOLOC.TO.LATITUDE, r.LOCATION.GEOLOC.TO.LONGITUDE));
}
}
}
var desc = r.TRAFFICITEMDESCRIPTION.find(x => x.TYPE === "short_desc").content;
return {
latlngs,
desc
}
})
console.log(d);
d.forEach((road)=>{
L.polyline(road.latlngs,{color: 'red'}).addTo(fg).bindPopup(road.desc);
});
map.fitBounds(fg.getBounds())
}
If this script is not working for you, please share your json file.
Ok, so I've found a solution for this task. Apparently I was on a good path, I only needed to optimize my implementation.
What I had to do to achieve appropriate performance is:
Create custom CircleMarker extension which would draw custom icon on canvas
Create JS worker which would fetch the data from a given URL, transform it to GeoJSON and return GeoJSON to it's listener
Create custom GridLayer implementation, which, in fetchTile function, creates worker instance, passes it a link with appropriate [Z]/[X]/[Y] coordinates already set, adds listener, which listens for worker's done event and returns empty tile
On worker's done event, custom GridLayer implementation creates GeoJSON layer, adds it to the dictionary with coordinates as a key and, if zoom level is still the same - adds that layer to the map
Add zoomend observer on a map, which removes any layers that does not match current zoom level from the map
Now the map is definitely usable and works way faster than original HERE JS API.
P.S. Sorry, but I can't share the implementation itself due to our company policies.

view panoramic image on google map

function initPano() {
// Set up Street View and initially set it visible. Register the
// custom panorama provider function. Set the StreetView to display
// the custom panorama 'reception' which we check for below.
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('map'), {
pano: 'reception',
visible: true,
panoProvider: getCustomPanorama
});
}
// Return a pano image given the panoID.
function getCustomPanoramaTileUrl(pano, zoom, tileX, tileY) {
// Note: robust custom panorama methods would require tiled pano data.
// Here we're just using a single tile, set to the tile size and equal
// to the pano "world" size.
return 'http://bestofdiscus.gr/portals/0/Discus-Header-WR.jpg';
}
function getCustomPanorama(pano, zoom, tileX, tileY) {
if (pano === 'reception') {
return {
location: {
pano: 'reception',
description: 'Google Sydney - Reception'
},
links: [],
// The text for the copyright control.
copyright: 'Imagery (c) 2010 Google',
// The definition of the tiles for this panorama.
tiles: {
tileSize: new google.maps.Size(1024, 512),
worldSize: new google.maps.Size(1024, 512),
centerHeading: 105,
getTileUrl: getCustomPanoramaTileUrl
}
};
}
}
In this block of code, i don't understand the parameters :pano, zoom, tileX, tileY in the function getCustomPanoramaTileUrl. I understand that, without using these parameter, the function will return an url of image.
my question is:
1/What do these parameters use for and how to use it ?
2/What is a pano ID (i have been searching for it a lot but still can not understand)
What are you talking about?
You may be thinking, "why is my question downvoted?" (PS: I didn't do it!). When asking a question, slapping random code with no context whatsoever will leave anyone trying to help you just as lost as you.
Though the code is useful, your question is missing important information:
What technologies are you using? Any APIs?
What have you tried?
Where is that code from?
Any links to any documentation? What is the context?
Before making a question, always make sure to read the following page https://stackoverflow.com/help/how-to-ask
Your code, where does it come from?
After doing some digging and some research I was able to find that your code is actually a piece of code from the Google Documentation, Custom Street View panoramas.
With this in mind Google has some documentation on the matter that will help you understand what is going on with your code:
https://developers.google.com/maps/documentation/javascript/streetview#TilingPanoramas
I read the documentation, but I still don't get it!
Although Google talks about Custom Panoramas with multiple views, the example provided is too simple to illustrate the full potential of the resources Google provides you.
Now, regarding your specific question...
What are pano, zoom, tileX, tileY used for?
In the code example that you provided, they are used for... nothing. You could literally remove them from getCustomPanoramaTileUrl and the code would still work.
So, what are they used for? Well, according to the References Documentation for StreetView, these parameters have the following objective:
Gets the tile image URL for the specified tile. pano is the panorama
ID of the Street View tile. tileZoom is the zoom level of the tile.
tileX is the x-coordinate of the tile. tileY is the y-coordinate of
the tile. Returns the URL for the tile image.
Now, if this is still, confusing, I will try to explain.
Custom panoramas are sets of images, put together, like in the image bellow:
When using a real panoramic view, you want to pass a set of images, and the StreetView object needs to know which set of images you are referring to (panoId), at which zoom level (zoom) and inside the set, the X and Y positions of the image you are currently seeing (tileX and tileY).
In the example you provided, since it is extremely simple, none of this is used because you always return the same image no matter what. But in a more complex example, that uses a set of images, this information would be crucial to let the StreetView know where you are looking at in order to display the correct image.
Hope it helps!

How to get max zoom for maptype in location

On Google Maps' JS API reference page, it says that the method getMaxZoomAtLatLng:
Returns the maximum zoom level available at a particular LatLng for
the Satellite map type.
For some reason, the terrain maptype bottoms out at level 15 in Calgary (for example) but the Satellite maptype can go all the way to zoom 19. I have two map services running simulataneously, and I want the maps to be in sync, but they can't sync up if they can't reach the same zoom level.
So, basically I want to know when the terrain map (or any maptype) can't cope, and trigger some special case functions.
Is there a method, or an alternative, for getting the maximum zoom for a location for a specific map type (since the above mentioned method only works for Satellite)?
Well, one solution I've decided to go with in the meantime is to attach a zoom-end handler to my ArcGIS map (could easily do this with Leaflet as well) and a maptypeid_changed handler to the Google map.
So, for the ArcGIS map (eMap) I did this:
eMap.on('zoom-end', function (e) {
// map zooms are synced
gMap.setCenter(esri.geometry.webMercatorToGeographic(e.extent.getCenter()));
gMap.setZoom(e.level);
// if the google map couldn't do it, reset eMap
if (gMap.getZoom() !== e.level) {
eMap.setZoom(gMap.getZoom());
// runs the handler again
}
});
And if the google map was set to Satellite, then changed, it also needed to trigger the same check, so I forced it to execute another zoomEnd handler:
google.maps.event.addListener(gMap, 'maptypeid_changed', function () {
// for some reason, ESRI has issues setting zoom to current zoom
// so it has to run an initial check before calling zoomEnd
if (gMap.getZoom() !== eMap.getZoom()) {
eMap.setZoom(gMap.getZoom());
}
});
Hope this helps someone, but really, I'm looking forward to seeing a better solution than this. Seems like an awfully complicated approach to merely firing a function if Google's maptype can't reach a certain zoom level.

How to set up the layer order with Google Maps API?

I'm developing a web mapping site (using google maps api 3.0 and javascript) that combines wms layers and ground overlays (uploaded rasters) that are displayed on top of google maps. The software is working well except that I'm having problems controlling the draw order of the layers. I would like to have the wms layer (the NRCS soils layer) displayed on top of the custom raster images, with the google maps as the base layer. Currently, the wms layer displays as expected on top of the google maps layer, but is covered by the raster layer. The question is: does the google maps api allow control of the order that layers are displayed (in my case the vector layer on top of raster layer on top of google maps)? I have tried setting the zindex of the display order, but that has not worked (but I could easily be missing something).
WMS layers are also rasters, not vectors -- I assume you are using an ImageMapType along with your GroundOverlay?
Leaving that aside, there is currently no way to control the layer ordering once they have been added to the map.
As a hack (untested) you may wish to add the layers in the order you wish them to be drawn, with some timeout between... I think this may work (again, untested).
(optional).
how i order it.
first i create layer in object like this.
layer = {};
layer.nrcs_soils= new google.maps.ImageMapType({
getTileUrl: function (coord, zoom) {
return getTileWmsUrl(coord, zoom, "nrcs_soils");
},
tileSize: new google.maps.Size(256, 256),
opacity: 1,
name:'nrcs_soils',
alt:{
layer_name:'nrcs_soils'
,order : 0
},
isPng: true
});
after that i create simple function add layer to map.
add_layer = function(layer_name){
//-- get order from object layer
var order_layer =layer[layer_name].alt.order;
map.overlayMapTypes.insertAt(order_layer ,layer[layer_name]);
}
just call this function for add and order layer from your setting on your object layer.
add_layer("nrcs_soils");

Bing Maps API v7 limit by bounds

So I'm trying to use the Search Module of the Bing Maps AJAX API (v7), and I've noticed that in the Interactive SDK for it you can pass in a property called bounds which you give a bounding box to search within. The example simply uses the map's current bounding box so theoretically, if you zoom in, a new search should simply show you results within your zoomed in area, right?
Well here's the issue: Add the following code at the end of the example code in the Interactive SDK:
Microsoft.Maps.Events.addHandler(map, 'viewchange', searchRequest);
What this should do is every time you move around the map or zoom in or out, it should fire a new search with the new bounding area of the map... I say this because of the line that looks like this: bounds: map.getBounds(),. What actually happens is that it bounces back to where it was initially before zooming.
Call me crazy, but is the bounds property just being completely ignored? Does anyone know how to limit the search results to the currently visible map area?
Lastly: Is it just me, or are the API docs for V7 rather incomplete? I've managed to find a few things by inspecting stuff in the Chrome console that doesn't appear in the API docs.
Update: This is what my call to the search function looks like:
searchManager.search({
bounds: map.getBounds(),
callback: searchSuccess,
count: 20,
entityType:"Business",
errorCallback: searchFail,
startIndex: 0,
userData: userData,
what: what,
where: search
});
I have not personally used on view changed as I'm not sure that was available when I migrated from 6.0.
I'll share an alternative route I went that gets the trick done.
My search functionality also puts a Microsoft.Maps.Pushpin exactly where the user searched ("You are here!").
I then I create a boundary from the pushpin:
var viewBoundaries = Microsoft.Maps.LocationRect.fromLocations(pushpin.getLocation());
Then set the Map.setView properties for bounds. (Aswell as zoom in my case)
map.setView({ bounds: viewBoundaries });
map.setView({ zoom: 10 });
If you are not using a pushpin, you can simply create the view boundary from the location class.
MSDN Location Class

Categories