Switching between two overlays in leaflet.js - javascript

I need to have an optional overlay above map that switches between two different WMS layers in leaflet.js if a certain map is selected (if layerX is turned on in LayerControl, layer1 is to be replaced by layer2, and when (Tile)layerX is no longer selected, replace layer2 by layer1 again), so i have listener on overlayadd and overlayremove (
map.on('overlayadd', function(layer){if(layer.name === "layerX"){
layers_on = !!map.hasLayer(layer1);
layer1.remove();
layer_selector.removeLayer(layer1);
if(layers_on){map.addLayer(layer2);
layer_selector.addOverlay(layer2, "layer2");
}});
map.on('overlayremove', function(layer){if(layer.name === "layerX"){
layers_on = !!map.hasLayer(layer2);
layer2.remove();
layer_selector.removeLayer(layer2);
if(layers_on){map.addLayer(layer1);}
layer_selector.addOverlay(layer1, "layer1");
}});
Code works fine when switching LayerX on, however when I remove it with layer2 on, it doesn't actually remove it, just replaces it in layer_control and adds layer1 on top of it
Simply said I need a overlay in LayerControl that dynamically shows one of two maps, if LayerX in on then show Layer1 in other case show Layer2. (and the layer itself is optional)

Instantiate a L.Control.Layers, and add your two L.TileLayer.WMSs as "base layers" in that control.
The name might be deceiving: what it means is that, for a given L.Control.Layers, the layers passed as "base layers" are mutually exclusive. They do nto need to be thematically base layers, and you can have more than one L.Control.Layers with a set of mutually exclusive L.Layers in each.

Related

combining overlays in mapbox / leaflet layers control

I'm trying to combine 2 or more overlays into one overlay checkbox. I'm using leaflet layers control with mapbox.js 1.6 to toggle my overlays. It doesn't matter to me if I combine them on mapbox.com into one data layer, or if I combine separate data layers in my JS code into one overlay checkbox, but I can't seem to do either. I'm exporting MBTiles from Tilemill to my Mapbox account.
Note that it's not an option to:
combine them in Tilemill (the single zoom level and square bounding box won't work for me across all layers)
add the various data layers to a single map project on Mapbox.com (I'd like it to be toggleabe by the user)
You can use L.layerGroup to combine layers
var group = L.LayerGroup([layer1, layer2];
// add default layers to map
map.addLayer(layer1);
// switcher
var baseLayers = {
"My Group": group,
// more layers
};
// add layer groups to layer switcher control
var controlLayers = L.control.layers(baseLayers).addTo(map);
You may be interested in this thread Leaflet layer control for basemap group layers
You can use the L.control.layers with the L.layerGroup. Here is the JSFiddle I wrote for this. You can add as many base or overlay layers you want.
Once you create the L.layerGroups, define the base and the overlay layers and add them to the control like this:
var controlLayers = L.control.layers(baseLayers, overlayMaps).addTo(map);

how to HIDE a groundoverlay instead of removing it by calling setMap(null)

I have multiple GroundOverlays loaded on the map and I try to keep them ordered. It seems the only thing I can do is to loaded (create the GroundOverlay object and setMap(map)) one by one (Please let me know if there are other better ways), whcih I can live with for now. However, I also have controls (checkboxes) to turn on/off a individual layer, which ends with the order is completely messed up. For instance, say I have L1, L2, L3 three layers ordered from bottom to top, if I turn off L2 and turn it on again, the L2 will be on the top of L3 as L2 was removed from the map when turned off.
My first attempt is to find a way to manage the order of the GroundOverlays, which I failed (could not find any); The second attempt is to try if I can 'hide' the layer when turn it off instead of removing the layer when calling setMap(null).
Any idear? Thanks!
You can set the opacity to zero:
myGroundOverlay.setOpacity(0);

In OpenLayers, Getting 1 Layer to stay over the other. (Z-Axis)

I have this map, which I show some red markers over and whenever a location is chosen from a list the current marker is painted blue and the map centers around it.
I achieve this by having 2 layers - one for the red markers which is drawn at the beginning and one which is redrawn whenever a point is chosen from the list.
I would like to define that the red marker layer will always appear above the blue marker layer. Effectively hiding the "current marker" indication. (The reason for this is complicated)
This link is to a page that works the way I don't want. The blue layer is on top of the red layer.
I tried to reverse the order by defining the graphicZIndex property for both the vector and in the layers.addFeature function.
I'm obviously doing something wrong and maybe someone can point me to what it is.
The way I define the z-axis:
currentPointLayer = new OpenLayers.Layer.Vector("Selected Point Layer", {
style : {
externalGraphic : 'marker-blue.png',
graphicHeight : 15,
graphicWidth : 15,
graphicZIndex : 1
},
rendererOptions: { zIndexing: true }
});
Again, I want to hide the blue marker behind the red markers layer.
You can either change the order of your layers as ilia choly stated.
Or, if you want to use zIndexing, you have to put all features into one layer, because zIndexing is only done within a single layer.
Have a look at this simple example about styling, that also uses zIndexing. It randomly creates some points in the map. If you zoom out, chances are good that two circles overlap and if you hoover over one, it will be highlighted and put on top.
So you want highlight a marker with different color whenever a point is selected? Managing it with 2 layers is really an overkill. You should be able to define a vector layer with style like this:
var currentPointLayer = new OpenLayers.Layer.Vector("Selected Point Layer", {
styleMap: new OpenLayers.StyleMap({
externalGraphic : '${markerUrl}',
pointRadius: 20
})});
map.addLayer(currentPointLayer);
Then you have to set attribute 'markerUrl' of every feature(i.e. feature.attributes.markerUrl) to 'marker-red.png' - that would be initial state of all features.
Then whenever feature is selected you change markerUrl attribute of selected feature to 'marker-blue.png' and(important) call
currentPointLayer.redraw();
Obviously you'll also have to set previously selected feature to 'marker-red.png' when new feature is selected.
in your init_map() function you're adding the red marker layer before the blue ones. Try switching them.
preparePointsOnMap(map, points); //red marker
if (!map.getCenter()) {
map_set_center(lon, lat, mZoom); //blue marker
}

mouse drag on kml features with OpenLayers

Link: http://www1.qhoach.com/
When you drag, this map is panned... But if you drag on KML features (icon with circle), nothing happens
First of all,in your application there are four level of maps including the vector layer you mentioned with circle icons in your question.
0: "Đường Sá" ||---> Overlay Tiles
1: "Vệ Tinh" ||---> Overlay Tiles
2: "TMS Overlay" ||---> Markers ~ Icons
3: "KML" ||---> Vector
Analysis:
Starting with zero to last one,only vector seems to be the last one,others stays as overlay tiles.In order to come this problem we have to focus on marker layer,namely features (icons).
As you have seen on map,click event for map has been triggered when you try to drag the map around.You can't drag because event registration is working for marker layer first not for the map.That means in order to drag the map,moving mouse(drag) after click must follow.Since you're trying this on vector layer,there is no chance to pass the event to overlay layers.
Solution:
I propose you two ways to achieve this bug-type problem.
Let this be the long way
There is a control in OpenLayers known as SelectFeature inherited from Handler.Feature.This control generally allows vector feature from a given layer on click on hover.Which means this handler can respond to mouse event related to any drawn features.Only callbacks are associated with features,needing one of them click.Now all we have to do is to fall click event back to as we pan for overlay tiles.
var selectFeat = new OpenLayers.Control.SelectFeature(
vector, {toggle: true, clickout:false});
selectFeat.handlers['feature'].stopDown = false;
selectFeat.handlers['feature'].stopUp = false;
map.addControl(selectFeat);//instance of map
selectFeat.activate();
Once this control is activated you have to ensure your layers to pass events through another layer.To do that,simply
layer.events.fallThrough = true;//both for vector and marker layers
After all these actions we made so far,one last thing left to do:
That's switching the order of markers and kml layer.
And this should be the easiest way
That's z-index on layers.You can check in above sequence of layers that the layer which has highest id has also highest z-index.
layer.setZIndex(...any number...);
In addition to this solution,easy way allows only you to drag through map,when all sudden clicking features of icons may lost without long way,so it's your choice to leave them behind.
Mouse events do not want to propagate through an svg Vector overlay to layers underneath.
The solution above demands all marker HTML layers have higher zindex than all Vector SVG layers.
The following CSS provides a potential/partial work-around, propagating events through the svg element, but only where there is no vector elements within the svg overlay:
/** Hack so mouse events propagate(bubble) through svg elements, but not the
images within svg */
.olLayerDiv svg {
pointer-events: none;
}
.olLayerDiv svg * {
pointer-events: auto;
}
Combine the above CSS while adding fallThrough:true to all OpenLayers events objects within maps, layers, and controls.
// map events
var map = new OpenLayers.Map(div, { fallThrough:true } );
// layer events
var lvec = new OpenLayers.Layer.Vector( .... );
lvec.events.fallThrough = true
map.addLayers([lvec])
// all map controls
var ctrl = new OpenLayers.Control.SelectFeature( lvec, {...
fallThrough: true, autoActivate:true });
map.addControl( ctrl )

How to set default view in OpenLayers, WITHOUT restricting bounds?

Based on samples, I can see that you can set a default view in OpenLayers by saying something along the lines of:
var bounds = new OpenLayers.Bounds(-125, 25, -65, 50);
var map = new OpenLayers.Map('map', {restrictedExtent: bounds });
However, this also (as the name implies), restricts me to be able to ONLY navigate within these bounds. I can zoom out and see things outside of these bounds, but I can't then zoom back onto them, or scroll to them.
I've tried not having any restrictedExtent (or making it the entire map), but then I can't get it to focus on the area I want. I tried using:
map.setCenter(new OpenLayers.LonLat(0,0), 3);
console.log(map.getCenter());
To set the zoom and the center...but it doesn't seem to do ANYTHING, other than set the variable "center" which I can then read from map.getCenter() (if I don't set it, it's null, if I do set it, I can see it...but the map itself stays fully extended and it's center doesn't seem to change at all...)
The Map layer I am using is:
OpenLayers.Layer.OSM.Mapnik
with displayOutsideMaxExtent set to true... I'm really at a loss here.
My goal is to have a default region of the world zoomed in to and in view (such as the United States), with the option of viewers being able to go outside the default to view things.
I think I've figured it out. For whatever reason, the zoom was never changing, but the center apparently WAS moving (it was just so zoomed out I couldn't tell). Add to the fact that I needed to transform the center to use the google projection, and it seems to work just fine.
What I ended up doing was:
var lonlat = new OpenLayers.LonLat(20,37).transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
map.setCenter(lonlat);
map.zoomTo(4);

Categories