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

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");

Related

Calling a Javascript method from the Bokeh Google Maps wrapper (fitBounds())

I have a bokeh Google maps plot with several Lat/ Lng data points, and I would like to use the fitBounds() method of the Google Maps v3 API to set the zoom level.
I have a Google Maps plot up and running, displaying on my site and showing the data points, but I need to set the zoom manually.
import bokeh.io
import bokeh.models
import bokeh.plotting
import pandas as pd
data = {
'Latitude [deg]': [18.46, 25.7, 32.3],
'Longitude [deg]': [-66, -80.2, -64.8],
}
data_frame = pd.DataFrame.from_dict(data)
data_source = bokeh.models.ColumnDataSource(data_frame)
mean_lat = data_frame['Latitude [deg]'].mean()
mean_lng = data_frame['Longitude [deg]'].mean()
gmap_options = bokeh.models.GMapOptions(lat=mean_lat, lng=mean_lng, zoom=10, map_type='satellite')
xy_gmap = bokeh.plotting.gmap('SuPeRSeCrEtAPIkey', gmap_options)
xy_gmap.circle(x='Longitude [deg]', y='Latitude [deg]', source=data_source, color="red")
# A callback like this? Could make the call in JavaScript after the page is loaded, and update map zoom??
# xy_gmap.fitBounds(x='Longitude [deg]', y='Latitude [deg]', source=data_source)
bokeh.io.show(xy_gmap)
I would like the bounds of the map to enclose all points in my dataframe, at the lowest zoom possible (as is done in Javascript by fitBounds() ). Currently, the map can only zoom to the manually set level.
As of Bokeh 1.2, there is no built-in way to accomplish this. The only suggestion I can offer is to note that there is a global Bokeh.index on the JavaScript side, and in that there is GMapPlotView for the corresponding GmapPlot that you made. This view has an attribute .map that is the actual Google map object. You could call the fitBounds method on that from JavaScript code. Bokeh GMapPlot objects follow Google's lead wrt to plot bounds, so if they get updated, the axes, etc. should respond.
Otherwise, I can only suggest opening a GitHub issue to discuss adding this as a new feature.
Starting an answer for both methods described by bigreddot (using JS Bokeh.index and Python integration)
Bokeh.index
In the Javascript Console, you can use the following commands (should be self explanatory to get this into some JS code)
> var gmapPlotView;
> for (var property in Bokeh.index) { if (Bokeh.index[property].constructor.name == 'GMapPlotView') {gmapPlotView = Bokeh.index[property];} } // Get the correct object, in the case that you have multiple plots, but only one map plot
> var bounds = gmapPlotView.map.getBounds(); // To start from existing bounds
> var bounds = google.maps.LatLngBounds(); // To start with fresh bounds
> var place = new google.maps.LatLng(45.5983128 ,8.9172776); // Coordinates of place to put bounds, repeat for all points
> bounds.extend(place); // Add each place to the bounds object
> gmapPlotView.map.fitBounds(bounds); // Set the maps new bounds
Note that the Bokeh google maps implementation does not plot your data on the Google Maps data layer, but on a bokeh canvas above the map (that is why there is a lag when panning the map between map tiles and your graphs).
Python Integration
In process....

Is it possible to use Tilestache with HERE maps Javascript API?

I have been browsing the HERE Maps API for Javascript docs for a while now and found no information whther it was possible to use custom tiles from Tilestache in HERE Maps API for Javascript.
My question to you who are more experienced with this API than me: Is it possible to use custom tiles at all in HERE Maps API for Javascript?
Many thanks in advance!
It's possible to use custom map tiles with here maps. You can find an example of how to do it here:
https://developer.here.com/api-explorer/maps-js/v3.0/infoBubbles/custom-tile-overlay
I recommend checking the full example, but in any case the key points are these:
1) create a tile provider and specify the url format
var tileProvider = new H.map.provider.ImageTileProvider({
// We have tiles only for zoom levels 12–15,
// so on all other zoom levels only base map will be visible
min: 12,
max: 15,
getURL: function (column, row, zoom) {
... omitted
// The Old Berlin Map Tiler follows the TMS URL specification.
// By specification, tiles should be accessible in the following format:
// http://server_address/zoom_level/x/y.png
return 'tiles/'+ zoom+ '/'+ row + '/'+ column+ '.png';
}
}
});
2) Create a layer and add it to the map
// Now let's create a layer that will consume tiles from our provider
var overlayLayer = new H.map.layer.TileLayer(tileProvider, {
// Let's make it semi-transparent
opacity: 0.5
});
// Finally add our layer containing old Berlin to a map
map.addLayer(overlayLayer);

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.

google Maps: $.goMap() with custom overlayMapType

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)

Creating a map using only toggleable overlays?

I'm trying to create map (using the Google Maps JavaScript API V3) which consists of several partially-transparent layers. By default, these layers should all be overlaid on top of one another to form a complete map, but the user should be able to turn any combination of them on or off (while preserving order) to create whatever view they prefer.
So far, I've had a great deal of luck getting this working for a single layer using map.mapTypes, but when adding all the layers via map.overlayMapTypes, I've hit a couple of snags:
The map doesn't seem to get fully initialized if map.setMapTypeId() is not called (no controls appear and the map is not correctly centered) and it cannot be called with an overlay.
It isn't clear how to toggle the visibility of an overlay without directly modifying the map.overlayMapTypes array, which complicates keeping them correctly ordered. I'd much prefer something analogous to the Traffic/Transit/Photos/etc. control available within Google Maps itself.
Here's the initialize function I'm working with. I'd post a link, but the map imagery isn't publicly available:
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 0,
center: center
});
/* if these lines are uncommented, the single layer displays perfectly */
//map.mapTypes.set("Layer 3", layers[3]);
//map.setMapTypeId("Layer 3");
//return;
var dummy = new google.maps.ImageMapType({
name: "Dummy",
minZoom: 0,
maxZoom: 6,
tileSize: new google.maps.Size(256, 256),
getTileUrl: function() {return null; }
});
map.mapTypes.set("Dummy", dummy);
map.setMapTypeId("Dummy");
// layers is an array of ImageMapTypes
for (var i = 0; i < layers.length; i++) {
map.overlayMapTypes.push(layers[i]);
}
}
As you can see, I've tried creating a "dummy" maptype (which always returns null for tile URLs) to serve as the base map. While this does cause the controls to display, it still doesn't center correctly.
What's the best way to create a map which consists only of toggleable overlays?
Update: Turns out the dummy maptype works perfectly well if you also remember to set a projection. That's one problem solved, at least. :-)
I use ImageMapType, but I don't add it to mapTypes. I just add it to overlayMapTypes and when I need to remove it I use setAt to set the entry in overlayMapTypes to null.
You will need to add individual controls to the UI that toggle the individual layers.

Categories