161 lines
5.3 KiB
JavaScript
161 lines
5.3 KiB
JavaScript
/* Copyright (c) 2019 Jean-Marc VIGLINO,
|
|
released under the CeCILL-B license (French BSD license)
|
|
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
|
*/
|
|
import ol_source_Vector from 'ol/source/Vector.js'
|
|
import {tile as ol_loadingstrategy_tile} from 'ol/loadingstrategy.js'
|
|
import {createXYZ as ol_tilegrid_createXYZ} from 'ol/tilegrid.js'
|
|
import ol_format_GeoJSON from 'ol/format/GeoJSON.js'
|
|
import ol_ext_Ajax from '../util/Ajax.js'
|
|
|
|
/** A vector source to load WFS at a tile zoom level
|
|
* @constructor
|
|
* @fires tileloadstart
|
|
* @fires tileloadend
|
|
* @fires tileloaderror
|
|
* @fires overload
|
|
* @extends {ol.source.Vector}
|
|
* @param {Object} options
|
|
* @param {string} options.typeName WFS type name parameter
|
|
* @param {string} [options.version=1.1.0] WFS version to use. Can be either 1.0.0, 1.1.0 or 2.0.0.
|
|
* @param {string} [options.outputFormat=application/json] WFS outputFormat parameter
|
|
* @param {number} [options.tileZoom=14] zoom to load the tiles
|
|
* @param {number} [options.maxFeatures] maximum features returned in the WFS
|
|
* @param {number} [options.featureLimit=Infinity] maximum features in the source before refresh, default Infinity
|
|
* @param {boolean} [options.pagination] experimental enable pagination, default no pagination
|
|
*/
|
|
var ol_source_TileWFS = class olsourceTileWFS extends ol_source_Vector {
|
|
constructor(options) {
|
|
options = options || {}
|
|
if (!options.featureLimit) options.featureLimit = Infinity
|
|
|
|
// Tile loading strategy
|
|
var zoom = options.tileZoom || 14
|
|
var sourceOpt = {
|
|
strategy: ol_loadingstrategy_tile(ol_tilegrid_createXYZ({ minZoom: zoom, maxZoom: zoom, tileSize: 512 }))
|
|
}
|
|
|
|
// Loading params
|
|
var format = new ol_format_GeoJSON()
|
|
var url = new URL(options.url)
|
|
// Get non standard options (apikey)
|
|
var search = url.search.replace(/^\?/,'').split('&')
|
|
url = url.origin + url.pathname
|
|
var std = /^service$|^request$|^version$|^typename$|^outputFormat$|^maxFeatures$|^bbox$|^srsname$/i;
|
|
search.forEach(function(s) {
|
|
var name = s.split('=')[0]
|
|
if (!std.test(name)) {
|
|
url += (/\?/.test(url) ? '&' : '?') + s;
|
|
}
|
|
})
|
|
// Query url
|
|
url = url
|
|
+ (/\?/.test(url) ? '&' : '?')
|
|
+ 'service=WFS'
|
|
+ '&request=GetFeature'
|
|
+ '&version=' + (options.version || '1.1.0')
|
|
+ '&typename=' + (options.typeName || '')
|
|
+ '&outputFormat=' + (options.outputFormat || 'application/json');
|
|
|
|
if (options.maxFeatures) {
|
|
url += '&maxFeatures=' + options.maxFeatures + '&count=' + options.maxFeatures
|
|
}
|
|
|
|
var loader = { loading: 0, loaded: 0 }
|
|
|
|
// Loading fn
|
|
sourceOpt.loader = function (extent, resolution, projection) {
|
|
if (loader.loading === loader.loaded) {
|
|
loader.loading = loader.loaded = 0
|
|
if (this.getFeatures().length > options.maxFeatures) {
|
|
this.clear()
|
|
this.refresh()
|
|
}
|
|
}
|
|
loader.loading++
|
|
this.dispatchEvent({
|
|
type: 'tileloadstart',
|
|
loading: loader.loading,
|
|
loaded: loader.loaded
|
|
})
|
|
this._loadTile(this._url, extent, projection, format, loader)
|
|
}
|
|
|
|
super(sourceOpt)
|
|
|
|
this._url = url
|
|
this.set('pagination', options.pagination)
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
_loadTile(url, extent, projection, format, loader) {
|
|
var req = url
|
|
+ '&srsname=' + projection.getCode()
|
|
+ '&bbox=' + extent.join(',') + ',' + projection.getCode()
|
|
if (this.get('pagination') && !/&startIndex/.test(url)) {
|
|
req += '&startIndex=0'
|
|
}
|
|
ol_ext_Ajax.get({
|
|
url: req,
|
|
success: function (response) {
|
|
loader.loaded++
|
|
if (response.error) {
|
|
this.dispatchEvent({
|
|
type: 'tileloaderror',
|
|
error: response,
|
|
loading: loader.loading,
|
|
loaded: loader.loaded
|
|
})
|
|
} else {
|
|
// Load features
|
|
var features = format.readFeatures(response, {
|
|
featureProjection: projection
|
|
})
|
|
if (features.length > 0) {
|
|
this.addFeatures(features)
|
|
}
|
|
// Next page?
|
|
let pos = response.numberReturned || 0
|
|
if (/&startIndex/.test(url)) {
|
|
pos += parseInt(url.replace(/.*&startIndex=(\d*).*/, '$1'))
|
|
url = url.replace(/&startIndex=(\d*)/, '')
|
|
}
|
|
// Still something to load ?
|
|
if (pos < response.totalFeatures) {
|
|
if (!this.get('pagination')) {
|
|
this.dispatchEvent({ type: 'overload', total: response.totalFeatures, returned: response.numberReturned })
|
|
this.dispatchEvent({
|
|
type: 'tileloadend',
|
|
loading: loader.loading,
|
|
loaded: loader.loaded
|
|
})
|
|
} else {
|
|
url += '&startIndex=' + pos
|
|
loader.loaded--
|
|
this._loadTile(url, extent, projection, format, loader)
|
|
}
|
|
} else {
|
|
this.dispatchEvent({
|
|
type: 'tileloadend',
|
|
loading: loader.loading,
|
|
loaded: loader.loaded
|
|
})
|
|
}
|
|
}
|
|
}.bind(this),
|
|
error: function (e) {
|
|
loader.loaded++
|
|
this.dispatchEvent({
|
|
type: 'tileloaderror',
|
|
error: e,
|
|
loading: loader.loading,
|
|
loaded: loader.loaded
|
|
})
|
|
}.bind(this)
|
|
})
|
|
}
|
|
}
|
|
|
|
export default ol_source_TileWFS
|