creating a cql filter in leaflet - leaflet

Please could I gain some assistance with the following problem. I would like to create a CQL filter in leaflet which filters data from GeoServer, with the data hosted in a PostGIS database.
For example, selecting a reservoir name from the NAME field in the database.The filter will be variable as the user can enter different names through an input dialog field.
I am displaying my layers as WMS, and although I was able to get an interactive filter working in openlayers 3, I still have had no like with leaflet.
I am new to the web development side of GIS and any help or pointers in the right direction would be greatly appreciated.
Kind regards,
Cameron

In leaflet you use TileLayer.WMS to plot wms layer on map. like this:
var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
layers: 'nexrad-n0r-900913',
format: 'image/png',
transparent: true,
attribution: "Weather data © 2012 IEM Nexrad"
});
You see some standard leaflet WMS options there like format, version ..crs etc.
But leaflet send all extra parameters/options in url to support non-standard WMS parameter . CQL_FILTER is one of them, so what you need to do is supply cql_filter options (column name is case sensitive):
var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
layers: 'nexrad-n0r-900913',
format: 'image/png',
transparent: true,
cql_filter: 'NAME=filterhere'
attribution: "Weather data © 2012 IEM Nexrad"
});

This is my first time posting to the forum and already I have received great help!
I have managed to get the cql_filter as suggested within my code as below:
var contours = L.tileLayer.wms('http://gis01-dbn:8080/geoserver/Inyaninga_243-198/wms', {
layers: 'Inyaninga_243-198:contours_3857',
format: 'image/png',
transparent: true,
cql_filter: 'elevation= 126',
});
Is there however any way to make this elevation parameter receive user input and update?
I have created a form in the html as such:
<form>
Elevation(m):<br>
<input type="text" id="myInput">
<input type="button" value="Elevation">
</form>
However, I am getting stuck with passing "myInput" into the cql_filter to accept a value which the user can enter.
I have tried creating a function housing the cql_filter but again cannot call this into the cql_filter option when loading the WMS.

Related

How to use Ordance Survey vector tiles with React-Leaflet?

I'm unsure of the correct syntax to add Ordnance Survey vector tiles to a React-Leaflet application.
The example code at https://labs.os.uk/public/os-data-hub-examples/os-vector-tile-api/vts-3857-basic-map loads some vector tile libraries from Mapbox:
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.13.1/mapbox-gl.js"></script>
<script src="https://unpkg.com/mapbox-gl-leaflet/leaflet-mapbox-gl.js"></script>
then uses this JavaScript syntax to load the OS vector tiles:
// Load and display vector tile layer on the map.
var gl = L.mapboxGL({
style: 'https://api.os.uk/maps/vector/v1/vts/resources/styles?key=' + apiKey,
transformRequest: url => {
return {
url: url += '&srs=3857'
}
}
});
(I've verified that my OS api key works in the stand-alone demo.)
How can accomplish the equivalent using React and Leaflet?
I'm using React-Leaflet to add Leaflet functionality to my React app, and I've tried adding react-leaflet-vector-tile-layer - I've verified that this works for vector tile layers supplied by Mapbox Studio:
<VectorTileLayer
styleUrl="mapbox://styles/my-org/my-style"
accessToken="my-key"
/>
I'm trying to use this approach for the Ordnance Survey vector tile layer too but it's not working as I probably have the syntax wrong:
<VectorTileLayer
styleUrl="https://api.os.uk/maps/vector/v1/vts/resources/styles?key=my-key"
/>
No error message is shown but the OS vector tile layer does not appear on the map. In the developer console I can see a PBF file has been downloaded but it doesn't draw on the map. Could this be because I'm missing the transformRequest function in their example? Assuming it's required, how can I add this transformation request when using react-leaflet-vector-tile-layer?
The answer came from Ted Piotrowski, the developer of the react-leaflet-vector-tile-layer library. I needed to add the transformRequest parameter using this syntax:
<VectorTileLayer
styleUrl="https://api.os.uk/maps/vector/v1/vts/resources/styles?key=my-key"
transformRequest={url => { return { url: url += '&srs=3857' }}}
/>

react-leaflet add layers dynamically

I'm starting to use react-leaflet and I came across a question: In my application the user fills out a form that then requests a rest service that returns a GeoJSON, which is then added as a new layer on my map. My question: How do I implement adding layers dynamically in react-leaflet?
Thank you.
The best approach is to create GeoJSON Layer wrapper for react-leaflet. There is a similar implementation of GeoJSON layer with clustering available in react-leaflet's plugins section.
Then you should add this layer to your map component and change it's data when you need to. So there is no need to add the layer dynamically but dynamically change data for it.
Check the leaflet's GeoJSON example to get the idea http://leafletjs.com/examples/geojson/.
The approach will work if you have one layer with changing data. But if you have different data sets you will need to add a GeoJSON layer for each of them.
<Map ...>
{this.props.datasets.map((ds, ix) => {
return (<GeoJSONOverlay data={ds} key={ix} />);
})}
</Map>
I have similar problem. I would like to clear and create marker layers dynamically. I think you can do it by getting reference to the actual map view react refs e.g.
<Map ref={Map => this.map = Map}>
later on you can then use this.map with normal Leaflet functions. Other option could be that you create layers in JSX same way I create markers:
{this.props.markers.map((i,index) => {
return (
<Marker key={i} position={i}>
<Popup>
<span>Great marker!</span>
</Popup>
</Marker>);
})}

Markercluster in Mapbox

I am following markercluster examples from Mapbox library, but can't solve my problem. If you guys take a look at my working example here, you will notice this line of code:
L.mapbox.featureLayer(markerLayer).on('ready', function(e) {
What I initally thought was I could put markers inside of markercluster featureLayer, but I guess it was a wrong approach. Any solutions? Thanks.
Example following here
The mapbox example you refer to makes an AJAX call to retrieve the GeoJSON data, hence it needs to attach an on "ready" listener.
In your case your GeoJSON data is defined in your scripts, so the "ready" event will not be triggered (besides, you should use L.mapbox.featureLayer with your GeoJSON object directly, not a Feature Layer).
You can simply use the eachLayer method to iterate through all created markers within the Feature Layer, and add them into your Marker Cluster Group.
var clusterGroup = new L.MarkerClusterGroup();
var markerLayer = L.mapbox.featureLayer(markers).eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup);
Updated Plunker: http://plnkr.co/edit/fN6xYcn1Lg532eLe39IS?p=preview

How to use a mapbox map in cartodb

I tried to integrate this map: https://a.tiles.mapbox.com/v4/felixmichel.kh7h21lp/page.html?access_token=pk.eyJ1IjoiZmVsaXhtaWNoZWwiLCJhIjoiZWZrazRjOCJ9.62fkOEqGMxFxJZPJuo2iIQ#11/47.6732/7.5352 into cartodb. But, it doesn't work. I work with cartodb.js because I added some more queries, so I needed the right link for this part:
L.tileLayer('https://a.tiles.mapbox.com/v4/felixmichel.kh7h21lp/page.html?access_token=pk.eyJ1IjoiZmVsaXhtaWNoZWwiLCJhIjoiZWZrazRjOCJ9.62fkOEqGMxFxJZPJuo2iIQ#11/47.6732/7.5352', {
attribution: 'CartoDB'
}).addTo(map);
Or if somebody knows a beautiful terrain map I am happy too.
Your tileLayer url is faulty, it expects the url to have placeholders for zoomlevel {z} and {x} and {y} for the axis values. You've used the url from an actual tile, which will not work.
L.tileLayer('https://a.tiles.mapbox.com/v4/felixmichel.kh7h21lp/{z}/{x}/{y}.png?access_token={token}', {
attribution: 'Mapbox',
subdomains: ['a','b','c','d'],
token: 'pk.eyJ1IjoiZmVsaXhtaWNoZWwiLCJhIjoiZWZrazRjOCJ9.62fkOEqGMxFxJZPJuo2iIQ'
}).addTo(map);
Note that as you can see, it also supports the {s} placeholder to load from multiple subdomains (which must be supported by your tileprovider. Mapbox does) which is much faster because browsers can simultaneously load from four subdomains at once. I also separated the access token from the url with the {token} placeholder to demonstrate that you can use your own custom tokens if needed.
Here's a working example of this on Plunker: http://plnkr.co/edit/lsTO9KzPMyzEKr06It1I?p=preview
And here's the reference for Leaflet's L.TileLayer: http://leafletjs.com/reference.html#tilelayer

Setting map language to English in Openstreetmap with LeafletJS

I'm using LeafletJS to add a map component to my app. Everything is fine and dandy except for the localization of the map. Some country names are shown in the local language (I'm assuming).
Is there a way to show the country names in English?
This is the current code that I use
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution : '© OpenStreetMap contributors',
noWrap : true
}).addTo(map);
The standard tile server of OSM tries to display labels in the local language whenever such data is available (local meaning the language of the country currently displayed, not your local language). The tiles, served by the tile server, already contain the labels, so you cannot remove them afterwards. But you can:
render them on your own (which requires suitable hardware) with an adjusted stylesheet, or
use tiles without labels and create a label overlay
try to see if there is a different tile server which only displays english labels. open mapquest for example has tiles based on OSM data where all labels are in english.
Map internationalization in the OSM wiki has some more examples
And always remember to comply with the tile usage policy of the tile server you choose.
All you need to do is to work with basemaps instead of openstreetmap
const mainLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png', {
minZoom: 3,
maxZoom: 17,
attribution: '© carto.com contributors'
});
mainLayer.addTo(this.map);
For German language
You can use this german tile server: https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png.
L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', {
...
})
...