Introduces getGetLegendGraphic method

Adds the `getGetLegendGraphic` method to `ImageWMS` and `TileWMS` source.
Also adds an example and corresponding tests.
This commit is contained in:
Kai Volland
2019-04-04 12:06:03 +02:00
committed by simonseyock
parent 7e3ed92ba6
commit f493f01bd0
6 changed files with 247 additions and 2 deletions

View File

@@ -0,0 +1,15 @@
---
layout: example.html
title: WMS GetLegendGraphic
shortdesc: Example of a WMS GetLegendGraphic.
docs: >
WMS supports the [getLegendGraphic request](https://docs.geoserver.org/latest/en/user/services/wms/get_legend_graphic/index.html).
This example demonstrates the use of the `getGetLegendGraphicUrl` method.
As a legend can be responsive to the scale it is updated on every change of the resolution.
tags: "GetLegendGraphic, getGetLegendGraphicURL, WMS"
---
<div id="map" class="map"></div>
Legend:
<div><img id="legend" src=""/></div>

View File

@@ -0,0 +1,47 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {Image as ImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
import ImageWMS from '../src/ol/source/ImageWMS.js';
import OSM from '../src/ol/source/OSM.js';
const wmsSource = new ImageWMS({
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'topp:states'},
ratio: 1,
serverType: 'geoserver'
});
const updateLegend = function(resolution) {
const graphicUrl = wmsSource.getGetLegendGraphicUrl(resolution);
const img = document.getElementById('legend');
img.src = graphicUrl;
};
const layers = [
new TileLayer({
source: new OSM()
}),
new ImageLayer({
extent: [-13884991, 2870341, -7455066, 6338219],
source: wmsSource
})
];
const map = new Map({
layers: layers,
target: 'map',
view: new View({
center: [-10997148, 4569099],
zoom: 4
})
});
// Initial legend
const resolution = map.getView().getResolution();
updateLegend(resolution);
// Update the legend when the resolution changes
map.getView().on('change:resolution', function(event) {
const resolution = event.target.getResolution();
updateLegend(resolution);
});

View File

@@ -191,6 +191,40 @@ class ImageWMS extends ImageSource {
1, sourceProjectionObj || projectionObj, baseParams); 1, sourceProjectionObj || projectionObj, baseParams);
} }
/**
* Return the GetLegendGraphic URL for the passed resolution.
* Return `undefined` if the GetLegendGraphic URL cannot be constructed.
* @param {number} resolution Resolution.
* @param {!Object} params GetLegendGraphic params. Default `FORMAT` is
* `image/png`. `VERSION` should not be specified here.
* @return {string|undefined} GetLegendGraphic URL.
* @api
*/
getGetLegendGraphicUrl(resolution, params) {
const layers = this.params_.LAYERS;
const isSingleLayer = !Array.isArray(layers) || this.params_['LAYERS'].length === 1;
if (this.url_ === undefined || !isSingleLayer) {
return undefined;
}
const mpu = this.getProjection() ? this.getProjection().getMetersPerUnit() : 1;
const dpi = 25.4 / 0.28;
const inchesPerMeter = 39.37;
const scale = resolution * mpu * inchesPerMeter * dpi;
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetLegendGraphic',
'FORMAT': 'image/png',
'LAYER': layers,
'SCALE': scale
};
assign(baseParams, params);
return appendParams(/** @type {string} */ (this.url_), baseParams);
}
/** /**
* Get the user-provided params, i.e. those passed to the constructor through * Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method. * the "params" option, and possibly updated using the updateParams method.

View File

@@ -8,7 +8,7 @@ import {assert} from '../asserts.js';
import {buffer, createEmpty} from '../extent.js'; import {buffer, createEmpty} from '../extent.js';
import {assign} from '../obj.js'; import {assign} from '../obj.js';
import {modulo} from '../math.js'; import {modulo} from '../math.js';
import {get as getProjection, transform, transformExtent} from '../proj.js'; import {get as getProjection, transform, transformExtent, METERS_PER_UNIT} from '../proj.js';
import {calculateSourceResolution} from '../reproj.js'; import {calculateSourceResolution} from '../reproj.js';
import {toSize, buffer as bufferSize, scale as scaleSize} from '../size.js'; import {toSize, buffer as bufferSize, scale as scaleSize} from '../size.js';
import TileImage from './TileImage.js'; import TileImage from './TileImage.js';
@@ -211,6 +211,41 @@ class TileWMS extends TileImage {
1, sourceProjectionObj || projectionObj, baseParams); 1, sourceProjectionObj || projectionObj, baseParams);
} }
/**
* Return the GetLegendGraphic URL for the passed resolution.
* Return `undefined` if the GetLegendGraphic URL cannot be constructed.
* @param {number} resolution Resolution.
* @param {!Object} params GetLegendGraphic params. Default `FORMAT` is
* `image/png`. `VERSION` should not be specified here.
* @return {string|undefined} GetLegendGraphic URL.
* @api
*/
getGetLegendGraphicUrl(resolution, params) {
const layers = this.params_.LAYERS;
const isSingleLayer = !Array.isArray(layers) || this.params_['LAYERS'].length === 1;
if (this.urls[0] === undefined || !isSingleLayer) {
return undefined;
}
const units = this.getProjection() && this.getProjection().getUnits();
const dpi = 25.4 / 0.28;
const mpu = METERS_PER_UNIT[units || 'm'];
const inchesPerMeter = 39.37;
const scale = resolution * mpu * inchesPerMeter * dpi;
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetLegendGraphic',
'FORMAT': 'image/png',
'LAYER': this.params_['LAYERS'],
'SCALE': scale
};
assign(baseParams, params);
return appendParams(/** @type {string} */ (this.urls[0]), baseParams);
}
/** /**
* @inheritDoc * @inheritDoc
*/ */

View File

@@ -189,7 +189,7 @@ describe('ol.source.ImageWMS', function() {
const source = new ImageWMS(options); const source = new ImageWMS(options);
pixelRatio = 1.325; pixelRatio = 1.325;
const image = const image =
source.getImage(extent, resolution, pixelRatio, projection); source.getImage(extent, resolution, pixelRatio, projection);
const uri = new URL(image.src_); const uri = new URL(image.src_);
const queryData = uri.searchParams; const queryData = uri.searchParams;
expect(queryData.get('FORMAT_OPTIONS')).to.be('dpi:119'); expect(queryData.get('FORMAT_OPTIONS')).to.be('dpi:119');
@@ -330,6 +330,63 @@ describe('ol.source.ImageWMS', function() {
}); });
}); });
describe('#getGetLegendGraphicUrl', function() {
it('returns the getLegenGraphic url as expected', function() {
const source = new ImageWMS(options);
const url = source.getGetLegendGraphicUrl(resolution);
const uri = new URL(url);
expect(uri.protocol).to.be('http:');
expect(uri.hostname).to.be('example.com');
expect(uri.pathname).to.be('/wms');
const queryData = uri.searchParams;
expect(queryData.get('FORMAT')).to.be('image/png');
expect(queryData.get('LAYER')).to.be('layer');
expect(queryData.get('REQUEST')).to.be('GetLegendGraphic');
expect(queryData.get('SERVICE')).to.be('WMS');
expect(queryData.get('VERSION')).to.be('1.3.0');
expect(queryData.get('SCALE')).to.be('357.14214285714274');
});
it('adds additional params as expected', function() {
const source = new ImageWMS(options);
const url = source.getGetLegendGraphicUrl(resolution, {
STYLE: 'STYLE_VALUE',
FEATURETYPE: 'FEATURETYPE_VALUE',
RULE: 'RULE_VALUE',
SLD: 'SLD_VALUE',
SLD_BODY: 'SLD_BODY_VALUE',
FORMAT: 'FORMAT_VALUE',
WIDTH: 'WIDTH_VALUE',
HEIGHT: 'HEIGHT_VALUE',
EXCEPTIONS: 'EXCEPTIONS_VALUE',
LANGUAGE: 'LANGUAGE_VALUE'
});
const uri = new URL(url);
expect(uri.protocol).to.be('http:');
expect(uri.hostname).to.be('example.com');
expect(uri.pathname).to.be('/wms');
const queryData = uri.searchParams;
expect(queryData.get('FORMAT')).to.be('FORMAT_VALUE');
expect(queryData.get('LAYER')).to.be('layer');
expect(queryData.get('REQUEST')).to.be('GetLegendGraphic');
expect(queryData.get('SERVICE')).to.be('WMS');
expect(queryData.get('VERSION')).to.be('1.3.0');
expect(queryData.get('SCALE')).to.be('357.14214285714274');
expect(queryData.get('STYLE')).to.be('STYLE_VALUE');
expect(queryData.get('FEATURETYPE')).to.be('FEATURETYPE_VALUE');
expect(queryData.get('RULE')).to.be('RULE_VALUE');
expect(queryData.get('SLD')).to.be('SLD_VALUE');
expect(queryData.get('SLD_BODY')).to.be('SLD_BODY_VALUE');
expect(queryData.get('FORMAT')).to.be('FORMAT_VALUE');
expect(queryData.get('WIDTH')).to.be('WIDTH_VALUE');
expect(queryData.get('HEIGHT')).to.be('HEIGHT_VALUE');
expect(queryData.get('EXCEPTIONS')).to.be('EXCEPTIONS_VALUE');
expect(queryData.get('LANGUAGE')).to.be('LANGUAGE_VALUE');
});
});
describe('#refresh()', function() { describe('#refresh()', function() {
let map, source; let map, source;

View File

@@ -299,6 +299,63 @@ describe('ol.source.TileWMS', function() {
}); });
}); });
describe('#getGetLegendGraphicUrl', function() {
it('returns the getLegenGraphic url as expected', function() {
const source = new TileWMS(options);
const url = source.getGetLegendGraphicUrl(0.1);
const uri = new URL(url);
expect(uri.protocol).to.be('http:');
expect(uri.hostname).to.be('example.com');
expect(uri.pathname).to.be('/wms');
const queryData = uri.searchParams;
expect(queryData.get('FORMAT')).to.be('image/png');
expect(queryData.get('LAYER')).to.be('layer');
expect(queryData.get('REQUEST')).to.be('GetLegendGraphic');
expect(queryData.get('SERVICE')).to.be('WMS');
expect(queryData.get('VERSION')).to.be('1.3.0');
expect(queryData.get('SCALE')).to.be('357.14214285714274');
});
it('adds additional params as expected', function() {
const source = new TileWMS(options);
const url = source.getGetLegendGraphicUrl(0.1, {
STYLE: 'STYLE_VALUE',
FEATURETYPE: 'FEATURETYPE_VALUE',
RULE: 'RULE_VALUE',
SLD: 'SLD_VALUE',
SLD_BODY: 'SLD_BODY_VALUE',
FORMAT: 'FORMAT_VALUE',
WIDTH: 'WIDTH_VALUE',
HEIGHT: 'HEIGHT_VALUE',
EXCEPTIONS: 'EXCEPTIONS_VALUE',
LANGUAGE: 'LANGUAGE_VALUE'
});
const uri = new URL(url);
expect(uri.protocol).to.be('http:');
expect(uri.hostname).to.be('example.com');
expect(uri.pathname).to.be('/wms');
const queryData = uri.searchParams;
expect(queryData.get('FORMAT')).to.be('FORMAT_VALUE');
expect(queryData.get('LAYER')).to.be('layer');
expect(queryData.get('REQUEST')).to.be('GetLegendGraphic');
expect(queryData.get('SERVICE')).to.be('WMS');
expect(queryData.get('VERSION')).to.be('1.3.0');
expect(queryData.get('SCALE')).to.be('357.14214285714274');
expect(queryData.get('STYLE')).to.be('STYLE_VALUE');
expect(queryData.get('FEATURETYPE')).to.be('FEATURETYPE_VALUE');
expect(queryData.get('RULE')).to.be('RULE_VALUE');
expect(queryData.get('SLD')).to.be('SLD_VALUE');
expect(queryData.get('SLD_BODY')).to.be('SLD_BODY_VALUE');
expect(queryData.get('FORMAT')).to.be('FORMAT_VALUE');
expect(queryData.get('WIDTH')).to.be('WIDTH_VALUE');
expect(queryData.get('HEIGHT')).to.be('HEIGHT_VALUE');
expect(queryData.get('EXCEPTIONS')).to.be('EXCEPTIONS_VALUE');
expect(queryData.get('LANGUAGE')).to.be('LANGUAGE_VALUE');
});
});
describe('#setUrl()', function() { describe('#setUrl()', function() {
it('sets the correct url', function() { it('sets the correct url', function() {
const source = new TileWMS(options); const source = new TileWMS(options);