Creating a custom control.layers class in leaflet - javascript

I have a page that displays maps using leaflet.js with many different base layers and overlays. I'd like to have separate layer controls for selecting the base maps and the overlays, and for the controls to have different icons.
To accomplish that I'm trying to on add a setButtonClass method to leaflet's L.control.layers that I can call after placing my 2nd button on the map, which would change its class and allow me to give it different styling.
So I'd initialize the controls like this:
var baseLayersControl = L.control.layers(baseMaps, null, {position: 'bottomright'});
var overlayControl = L.control.layers(null, overlayMaps, {position: 'bottomright'});
baseLayersControl.addTo(map);
overlayControl.addTo(map);
overlayControl.setButtonClass();
However, I can't get setButtonClass to change the class the way I want. I added this to leaflet-src.js:
setButtonClass: function () {
this.className = 'leaflet-control-layers2';
},
And added styling to leaflet.css for the leaflet-control-layers2 class and related classes with my new icon, but right now I'm just getting two standard layer controls on the map.

Have you checked out Leaflet.groupedlayercontrol? It groups and labels your layer control by base maps and overlays. I'd check there first and then see how you might be able to create two separate icons for base layers and overlays.

Related

mapboxgl.Marker() add to Layer instead Map

I want to use mapboxgl.Marker() since I need to build a custom < div> and stylize it by css.
But I also need to use:
map.queryRenderedFeatures() - to get information about visible markers on the screen
map.setLayoutProperty() - to filter markers like groups
Question: Can I use mapboxgl.Marker() to place it on Layer, not on Map?
Or can be another way of use mapboxgl.Marker() with map.queryRenderedFeatures() and map.setLayoutProperty()?
I see a possible hack: combine Layer with invisible layer-markers, and over them set mapboxgl.Marker(). This will allow me to use map.queryRenderedFeatures(), but map.setLayoutProperty(id, 'visibility', 'none') will still not work.

How to dynamically set shadow in Leaflet.js

I would like to dynamically set the shadow of a custom marker icon at runtime, because I want to emphasize the currently clicked icon. I'm using Leaflet 1.0. Things I've tried:
Adding a shadow at runtime with the createShadow function
Adding a blank png shadow image to the custom icon and changing it at runtime by either the createShadow function or directly modifying the shadow's image source
Here's some psuedocode:
function addMyShadow(marker) {
/* try Leaflet's `createShadow` function */
// directly modify marker: Uncaught TypeError: marker.createShadow is not a function
marker.createShadow('lib/images/shadow.png');
// the createShadow is available under options.icon,
// but this doesn't seem to change anything
marker.options.icon.createShadow('lib/images/shadow.png');
/* try directly modifying the shadow's image source */
// Successfully changes the `currectSrc` property,
// but also doesn't do anything to the icon on the map
marker._shadow.currentSrc = 'lib/images/shadow.png';
}
I also tried appending a custom class with -webkit-filter: drop-shadow, but I'm already using -webkit-filter to color a set of icons. I only want to change the selected icon, not the entire class. Apparently nesting -webkit-filter overwrites the outside -webkit-filter instead of stacking filters. So this isn't a viable option for me.
Currently I'm experimenting with adding a custom class that uses css drop-shadow; it seems like I can manually change the class at runtime, but I'm hoping there's some better built-in way to add a shadow. It's also not very pretty, because it makes the shadow square even if the image has transparency.
EDIT: I want the marker to be draggable (and have the shadow follow as the marker is dragged). So any solution with two icons would need to bind both icons together somehow.
I think you should have 2 L.icon objects: one without shadow and one with a shadow.
To show the shadow, you just switch L.Icon
marker.on('click', function(e) {
if(selectedMarker) {
if(selectedMarker !== e.target) { // selected marker is NOT this one
selectedMarker.setIcon(greenIcon);
e.target.setIcon(greenIconWithShadow);
selectedMarker = e.target;
}
else { // selected marker is this one
selectedMarker.setIcon(greenIcon);
selectedMarker = false;
}
}
else { // no marker selected
selectedMarker = e.target;
e.target.setIcon(greenIconWithShadow);
}
});
The shadow is part of the L.Icon and should follow when dragged
See example http://plnkr.co/edit/PNxzJqMbcRTuo0jWPGyj?p=preview

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

html instead of google maps marker image

Is it possible to display HTML instead of an image as a Google Maps Marker ?
What is the best way to do so?
I imagine that something like an invisible marker and a custom info-window might play a role in achieving this
You can use OverlayView class to create custom overlays with html elements - https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
Simple example - http://jsfiddle.net/BCr2B/
You might want to check this out: https://github.com/jonyt/gmaps-div-overlay
DivOverlay is a very simple container for HTML to be shown over a
Google Map at any position. All it does is calculate margins from the
map bounds so its entire contents are within the map. Take a look at
the demo. The constructor takes 3 arguments: the HTML container, the
map to attach to and the position of the overlay. DivOverlay has only
two functions: show() and hide(). Should be self-explanatory.

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
}

Categories