Skip to content

Instantly share code, notes, and snippets.

@yogiwinardhana
Forked from alfredotranchedone/BetterWMS
Created August 20, 2020 10:10
Show Gist options
  • Save yogiwinardhana/1df995ce2b31cdf10cd078d4d04f4a3d to your computer and use it in GitHub Desktop.
Save yogiwinardhana/1df995ce2b31cdf10cd078d4d04f4a3d to your computer and use it in GitHub Desktop.
L.TileLayer.BetterWMS.js extend L.TileLayer.WMS
There are a bunch of reasons why this is convoluted, mostly in building the URL to make the request:
1. You have to rely on an AJAX request, this example uses jQuery
2. To make a GetFeatureInfo request, you must provide a BBOX for a image, and the pixel coordinates for the part of the image that you want info from. A couple of squirrely lines of Leaflet code can give you that.
3. Output formats. The `info_format` parameter in the request. We don't know *a priori* which will be supported by a WMS that we might make a request to. See [Geoserver's docs](http://docs.geoserver.org/stable/en/user/services/wms/reference.html#getfeatureinfo) for what formats are available from Geoserver. That won't be the same from WMS to WMS, however.
4. WMS services return XML docs when there's a mistake in the request or in processing. This sends an HTTP 200, which jQuery doesn't think is an error.
5. added a php proxy and 2 new options (CORS workaround)
<!doctype html>
<html>
<head>
<title>WMS GetFeatureInfo</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.ie.css" />
<![endif]-->
<script src="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script>
<style type="text/css">
html, body, #map {
margin: 0px;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="L.TileLayer.BetterWMS.js"></script>
<script>
var map = L.map('map', {
center: [34,-111],
zoom: 7
});
var url = 'http://data.azgs.az.gov/arizona/wms';
L.tileLayer('http://{s}.tiles.mapbox.com/v3/rclark.map-wm3i8w1a/{z}/{x}/{y}.png').addTo(map);
L.tileLayer.betterWms(url, {
layers: 'azgs:mapunitpolys',
transparent: true,
format: 'image/png'
}).addTo(map);
</script>
</body>
</html>
L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
onAdd: function (map) {
// Triggered when the layer is added to a map.
// Register a click listener, then do all the upstream WMS things
L.TileLayer.WMS.prototype.onAdd.call(this, map);
map.on('click', this.getFeatureInfo, this);
},
onRemove: function (map) {
// Triggered when the layer is removed from a map.
// Unregister a click listener, then do all the upstream WMS things
L.TileLayer.WMS.prototype.onRemove.call(this, map);
map.off('click', this.getFeatureInfo, this);
},
getFeatureInfo: function (evt) {
// Make an AJAX request to the server and hope for the best
var url = this.getFeatureInfoUrl(evt.latlng),
showResults = L.Util.bind(this.showGetFeatureInfo, this);
$.ajax({
url: url,
success: function (data, status, xhr) {
var err = typeof data === 'string' ? null : data;
showResults(err, evt.latlng, data);
},
error: function (xhr, status, error) {
showResults(error);
}
});
},
getFeatureInfoUrl: function (latlng) {
// Construct a GetFeatureInfo request URL given a point
var point = this._map.latLngToContainerPoint(latlng, this._map.getZoom()),
size = this._map.getSize(),
params = {
request: 'GetFeatureInfo',
service: 'WMS',
srs: 'EPSG:4326',
styles: this.wmsParams.styles,
transparent: this.wmsParams.transparent,
version: this.wmsParams.version,
format: this.wmsParams.format,
bbox: this._map.getBounds().toBBoxString(),
height: size.y,
width: size.x,
layers: this.wmsParams.layers,
query_layers: this.wmsParams.layers,
info_format: 'text/html'
};
params[params.version === '1.3.0' ? 'i' : 'x'] = point.x;
params[params.version === '1.3.0' ? 'j' : 'y'] = point.y;
// return this._url + L.Util.getParamString(params, this._url, true);
var url = this._url + L.Util.getParamString(params, this._url, true);
/**
* CORS workaround (using a basic php proxy)
*
* Added 2 new options:
* - proxy
* - proxyParamName
*
*/
// check if "proxy" option is defined (PS: path and file name)
if(typeof this.wmsParams.proxy !== "undefined") {
// check if proxyParamName is defined (instead, use default value)
if(typeof this.wmsParams.proxyParamName !== "undefined")
this.wmsParams.proxyParamName = 'url';
// build proxy (es: "proxy.php?url=" )
_proxy = this.wmsParams.proxy + '?' + this.wmsParams.proxyParamName + '=';
url = _proxy + encodeURIComponent(url);
}
return url;
},
showGetFeatureInfo: function (err, latlng, content) {
if (err) { console.log(err); return; } // do nothing if there's an error
// Otherwise show the content in a popup, or something.
L.popup({ maxWidth: 800})
.setLatLng(latlng)
.setContent(content)
.openOn(this._map);
}
});
L.tileLayer.betterWms = function (url, options) {
return new L.TileLayer.BetterWMS(url, options);
};
<?php
/**
* PS: super basic template!
*
*/
// querystring parameter: same name of the WMS option
$url = $_GET['url'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,urldecode($url));
curl_setopt($ch, CURLOPT_REFERER, 'http://localhost');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment