OGC WFS-T client layer for leaflet.
Via npm:
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.1
where #v1.1.1 is version of specific release.
options: {
crs: L.CRS.EPSG3857,
showExisting: true,
geometryField: 'Shape',
url: '',
typeNS: '',
typeName: '',
opacity: 1,
style: {
color: 'black',
weight: 1
}
}
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://demo.opengeo.org/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 |
var map = L.map('map').setView([0, 0], 2);
var boundaries = new L.WFS({
url: 'http://demo.opengeo.org/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);
})
Extends leaflet classes with toGml(crs) function:
Triggers two type of events:
Markers geometry writes as posNode, for all other layers geometry writes as posList
Realization of OGC Filter Encoding v1.1.0
Filter implementations return only inner content of filter element.
Some considerations for all filter constructors:
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.
In standard there are two filters - GmlObjectID and FeatureID, but latest is marked as deprecated and so is not implemented.
Example:
var filter = new L.Filter.GmlObjectID(1);
result xml:
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:GmlObjectId xmlns:gml="http://www.opengis.net/gml" gml:id="1" />
</ogc:Filter>
var filter = new L.Filter.EQ('city', 'Perm');
filter.toGml()
result xml:
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>city</ogc:PropertyName>
<ogc:Literal>Perm</ogc:Literal>
</ogc:PropertyIsEqualTo>
This filter accept optional attributes object:
attributes: {
wildCard: '*',
singleChar: '#',
escapeChar: '!',
matchCase: true
}
var filter = new L.Filter.Like('city', '*perm*', { matchCase: false });
filter.toGml()
result xml:
<ogc:ogc:PropertyIsLike wildCard="*" singleChar="#" escapeChar="!" matchCase="false">
<ogc:PropertyName>city</ogc:PropertyName>
<ogc:Literal>*perm*</ogc:Literal>
</ogc:ogc:PropertyIsLike>
Example:
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:
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:BBOX>
<ogc:PropertyName>ogr_geometry</ogc:PropertyName>
<gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:lowerCorner>-74.227 40.712</gml:lowerCorner>
<gml:upperCorner>-74.125 40.774</gml:upperCorner>
</gml:Envelope>
</ogc:BBOX>
</ogc:Filter>
Example:
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:
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:Intersects>
<ogc:PropertyName>ogr_geometry</ogc:PropertyName>
<gml:Polygon xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326" srsDimension="2">
<gml:exterior>
<gml:LinearRing srsDimension="2">
<gml:posList>-74.227 40.712 -74.125 40.774 -74.175 40.734 -74.227 40.712</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</ogc:Intersects>
</ogc:Filter>
Editing plugin - Leaflet.Editable
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
L.easyButton('fa-save', function () {
wfst.save();
}, 'Save changes');
//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']);
demos for GML read format
demo for GeoJSON read format
demo filter bbox
MIT License