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 |
Basic WFS example - view
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:
- L.Marker
- L.Polygon
- L.Polyline
- L.MultiPolygon
- L.MultiPolyline
- L.LatLngBounds
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 layers
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:
- "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.
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