WFST plugin for Leaflet
npm install leaflet-wfstOGC WFS-T client layer for leaflet.
npm i leaflet-wfst --save
`
Via Bower:
`
bower i leaflet-wfst --save
`
From GitHub:
`
npm i -S git://github.com/Flexberry/Leaflet-WFST.git#v1.1.1F
`
where #v1.1.1 is version of specific release.Initialization options
`javascript
options: {
crs: L.CRS.EPSG3857,
showExisting: true,
geometryField: 'Shape',
url: '',
typeNS: '',
typeName: '',
opacity: 1,
style: {
color: 'black',
weight: 1
}
}`Example
`javascript
const wfstPointOptions = {
crs: L.CRS.EPSG4326,
showExisting: true,
geometryField: 'geom',
url: http://localhost:8080/geoserver/wfs,
typeNS: 'test',
typeName: 'test',
maxFeatures: 90,
opacity: 1,
style: function(layer) {
// you can use if statemt etc
return {
color: 'black',
weight: 1
}
}
};
const wfstPoint = new L.WFST(wfstPointOptions, new L.Format.GeoJSON({
crs: L.CRS.EPSG4326,
pointToLayer(geoJsonPoint, latlng) {
const layer = new L.CircleMarker(latlng, {
radius: 10,
});
return layer;
},
}));
wfstPoint.addTo(map);
`|option name|default|comment|
|-----------|-------|-------|
|crs|L.CRS.EPSG3857|spatial reference system for layer, should implement ICRS, for example Proj4Leaflet |
|showExisting|true|load existing features on create layer|
|geometryField|'Shape'|field for storing geometries, for non transaction services may be ommited|
|url|-|WFS url, for example http://geoserver.ics.perm.ru/geoserver/osm/ows
|typeNS|-|type namespace|
|typeName|-|type name|
|typeNSName|-|type namespace name|
|namespaceUri|-|namespace URI|
|opacity|1|layer's opacity|
|style|-|leaflet vector style. function or object|
|filter|-|any filter. see filter|
|maxFeatures|-|limit the amount of features returned|
|withCredentials|false|option to configure outgoing requests sending through XMLHttpRequest|
Basic WFS example - view
`javascript
var map = L.map('map').setView([0, 0], 2);var boundaries = new L.WFS({
url: 'http://geoserver.ics.perm.ru/geoserver/ows',
typeNS: 'topp',
typeName: 'tasmania_state_boundaries',
crs: L.CRS.EPSG4326,
style: {
color: 'blue',
weight: 2
}
}).addTo(map)
.on('load', function () {
map.fitBounds(boundaries);
})
`Methods
Extends leaflet classes with toGml(crs) function:
* L.Marker
* L.Polygon
* L.Polyline
* L.MultiPolygon
* L.MultiPolyline
* L.LatLngBoundsEvents
Triggers two type of events:
* load - triggers when both 'DescribeFeatureType' & 'GetFeature' requests succeed, and features have been successfully parsed into leaflet layers
* error - triggers when any 'DescribeFeatureType' or 'GetFeature' request fails, and features haven't been parsed into leaflet layersMarkers geometry writes as posNode, for all other layers geometry writes as posList
Filter
Realization of OGC Filter Encoding v1.1.0
Filter implementations return only inner content of filter element.
Some considerations for all filter constructors:
* "expression" - propertyName, literal, operator filter or function
* "propertyExpression" - if argument on this position is not Element and is not "expression" method it suspect to be a propertyName
* "literalExpression" - if argument on this position is not Element and is not "expression" it suspect to be a literal
|Name|Constructor|
|----|-----|
|ID|
|GmlObjectId|L.Filter.GmlObjectId(value id)|
|Comparisons|
|PropertyIsEqualTo|L.Filter.EQ(propertyExpression firstArgument, literalExpression secondArgument, bool matchCase)|
|PropertyIsNotEqualTo|L.Filter.NotEQ(propertyExpression firstArgument, literalExpression secondArgument, bool matchCase)|
|PropertyIsLessThan|L.Filter.LT(propertyExpression firstArgument, literalExpression secondArgument, bool matchCase)|
|PropertyIsGreaterThan|L.Filter.GT(propertyExpression firstArgument, literalExpression secondArgument, bool matchCase)|
|PropertyIsLessThanOrEqualTo|L.Filter.LEQ(propertyExpression firstArgument, literalExpression secondArgument, bool matchCase)|
|PropertyIsGreaterThanOrEqualTo|L.Filter.GEQ(propertyExpression firstArgument, literalExpression secondArgument, bool matchCase)|
|PropertyIsLike|L.Filter.Like(string propertyName,string likeExpression,object attributes)|
|PropertyIsNull|L.Filter.IsNull(string propertyName)|
|PropertyIsBetween|L.Filter.IsBetween(propertyExpression firstArgument, literalExpression lowerBoundary, literalExpression upperBoundary)|
|Operators|
|Add|L.Filter.Add(expression, expression)|
|Sub|L.Filter.Sub(expression, expression)|
|Mul|L.Filter.Mul(expression, expression)|
|Div|L.Filter.Div(expression, expression)|
|Logic|
|And|L.Filter.And(expression[, expression]*)|
|Or|L.Filter.Or(expression[, expression]*)|
|Not|L.Filter.Not(expression)|
|Spatial|
|BBox|L.Filter.BBox(string propertyName, latLngBounds bounds, ICRS crs)|
|Equals|L.Filter.Equals(string propertyName, Layer geometry, ICRS crs)|
|Disjoint|L.Filter.Disjoint(string propertyName, Layer geometry, ICRS crs)|
|Touches|L.Filter.Touches(string propertyName, Layer geometry, ICRS crs)|
|Within|L.Filter.Within(string propertyName, Layer geometry, ICRS crs)|
|Overlaps|L.Filter.Overlaps(string propertyName, Layer geometry, ICRS crs)|
|Crosses|L.Filter.Crosses(string propertyName, Layer geometry, ICRS crs)|
|Intersects|L.Filter.Intersects(string propertyName, Layer geometry, ICRS crs)|
|Contains|L.Filter.Contains(string propertyName, Layer geometry, ICRS crs)|
|Spatial distance buffer|
|DWithin|L.Filter.DWithin(string propertyName, Layer geometry, ICRS crs, value distance, string units)|
|Beyond|L.Filter.Beyond(string propertyName, Layer geometry, ICRS crs, value distance, string units)|
|Other|
|Function|L.Filter.Function(string functionName[, expression]*)|
|PropertyName|L.Filter.propertyName(string name)|
|Literal|L.Filter.literal(value)|
PropertyName and Literal is functions and returns Gml directly.
Examples
$3
In standard there are two filters - GmlObjectID and FeatureID, but latest is marked as deprecated and so is not implemented.
Example:
`javascript
var filter = new L.Filter.GmlObjectID(1);
`
result xml:
`xml
`$3
`javascript
var filter = new L.Filter.EQ('city', 'Perm');
filter.toGml()
`result xml:
`xml
city
Perm
`$3
This filter accept optional attributes object:
`javascript
attributes: {
wildCard: '*',
singleChar: '#',
escapeChar: '!',
matchCase: true
}
``javascript
var filter = new L.Filter.Like('city', 'perm', { matchCase: false });
filter.toGml()
`result xml:
`xml
city
perm
`$3
Example:
`javascript
var filter = new L.Filter.BBox('ogr_geometry', L.latLngBounds(L.latLng(40.712, -74.227), L.latLng(40.774, -74.125)), L.CRS.EPSG4326);
filter.toGml()
`result xml:
`xml
ogr_geometry
-74.227 40.712
-74.125 40.774
`$3
Example:
`javascript
var filter = new L.Filter.Intersects('ogr_geometry', L.polygon([L.latLng(40.712, -74.227), L.latLng(40.774, -74.125), L.latLng(40.734, -74.175)]), L.CRS.EPSG4326);
filter.toGml();
`
result xml:
`xml
ogr_geometry
-74.227 40.712 -74.125 40.774 -74.175 40.734 -74.227 40.712
`WFST Example
Editing plugin - Leaflet.Editable
`javascript
L.WFST.include(MultiEditableMixin);var wfst = new L.WFST({
url: 'http://myserver/geoserver/ows',
typeNS: 'myns',
typeName: 'POIPOINT',
style: {
color: 'blue',
weight: 2
}
}).addTo(map).once('load', function () {
map.fitBounds(wfst);
wfst.enableEdit();
});
map.on('editable:created', function (e) {
wfst.addLayer(e.layer);
});
map.on('editable:editing', function (e) {
wfst.editLayer(e.layer);
});
`to make "wfs:Transaction" POST request call save() method, example with Leaflet.EasyButton
`javascript
L.easyButton('fa-save', function () {
wfst.save();
}, 'Save changes');
`Layer properties
`javascript
//simple layer
layer = new L.Marker([0, 0]);
layer.feature = {
id: 1,
properties: {
a: 'a',
b: 'b'
}
};//get value by key 'a'
var a = layer.getProperty('a');
//change values
layer.setProperties({
a: 'b',
b:'a'
});
//add new property
layer.setProperties({
c:'c'
});
//delete properties
layer.deleteProperties(['a','b','c']);
``demo for GeoJSON read format
* Polygons
demo filter bbox
* BBox