-
Notifications
You must be signed in to change notification settings - Fork 25
MAPP
MAPP is a library for web mapping applications based on Openlayers map component.
The mapp.dictionary is an object proxy. The get handler will use the mapp.language (default: en
) value to lookup the requested key in the mapp.dictionaries. The English value will be returned if mapp.language entry has not been specified.
new Proxy({}, {
get: function(target, key, receiver){
if (mapp.dictionaries[mapp.language][key]) {
return mapp.dictionaries[mapp.language][key]
}
return mapp.dictionaries.en[key]
}})
The mapp.dictionaries object can be extended in any of the javascript modules imported into the mapp library.
Mapview is a decorator method. Methods and properties are assigned to the mapview object provided as argument. The decorated mapview object is returned.
export default (mapview) => {
Object.assign(mapview, {
srid: mapview.locale.srid || '3857',
addLayer,
fitView,
geoJSON,
getBounds,
infotip,
locate,
popup,
layers: {},
locations: {},
interactions: {
highlight: _highlight.bind(mapview),
draw: _draw.bind(mapview),
modify: _modify.bind(mapview),
zoom: _zoom.bind(mapview),
}
})
Valid mapview keys and values are:
mapp.Mapview({
host: '/mapp', // REQUIRED; Can be relative
target: 'Map', // REQUIRED; Can be string or instanceOf HTMLElement
hooks: true,
locale: {
extent: {
north: 62, //lat
east: 11, //lng
south: 48, //lat
west: -19, //lng
mask: true,
},
view: {
lat: 54.3,
lng: -4,
z: 4,
},
minZoom: 4,
maxZoom: 18,
},
scrollWheelZoom: true,
scalebar: 'metric', //'imperial'
controls: [new ol.control.Zoom()], // Adds OL zoom control
attribution: {
target: document.getElementById('Attribution'),
links: {
[`XYZ v${mapp.version}`]: "https://geolytix.github.io/xyz",
Openlayers: "https://openlayers.org",
}
}
})
Setting hooks: true
will update the URL parameter when the viewport changes.
The mapview.Map control is an OL Map interface assigned by the Mapview decorator.
The mapview.Map pointermove event updates the mapview.position and mapview.pointerLocation properties when triggered.
The mapview.Map mouseout event sets the mapview.position and mapview.pointerLocation properties to null when triggered.
The mapview.Map changeEnd event updates the lat, lng, and z URL view hooks when triggered.
The mapview.Map moveend event debounces the changeEnd evnt.
mapview.layers is a key/value list of layers which have been added to a mapview with the mapview.addLayer method. The layer key can be used to lookup a layer in the list. With hooks enabled on the mapview a comma seperated list of layers with display: true
is maintained as the layers URL parameter value.
mapview.locations is a key/value list of selected locations. A location key is composed of the location's layer key and id (eg. stores|23
). The mapp.location.get method will add a location to the locations list. With hooks enabled on the mapview a comma seperated list of location keys is maintained as the locations URL parameter value.
A single layer, or an array of layers provided as argument to the mapview.addLayer method will be cloned and assigned to the mapview.layers list. The layer.display flag will be set according to the current mapp hooks if hooks are enabled for the mapview. The layer.show() method will be called if layer.display is truthy.
Fits view[port] of the mapview.Map control to the provided extent. The options argument is passed on to the OL view.fit() method as opt_options. The options argument allows to override defaults for the duration of the transition animation and viewport padding.
The mapview.geoJSON method reads a single geoJSON geometry provided as params.geometry. The geometry will be transformed to the mapview.srid projection if an SRID/EPSG code is provided as params.dataProjection. The zIndex for the layer can provided as param. A new OL vector source and layer will be created. The layer will be added to the mapview.Map and returned. The style for the vector layer must be provided as params.Style.
mapview.geoJSON({
zIndex: infinity,
geometry: {
type: 'Point',
coordinates: entry.value,
},
dataProjection: '4326' // EPSG|SRID
// The Style param must be provided as OL Style object.
Style: mapp.utils.style({
strokeColor: "#F00",
strokeWidth: 2,
})
})
mapview.getBounds returns the calculated extent from the mapview.Map view[port]. The extent is returned as a object with north, east, west, and south keys for the individual edge values. The values are transformed to a target projection if an srid argument is provided as EPSG/SRID code.
The infotip method will create an .infotip
element with the content provided as HTML element. The infotip element position will update when a mapview pointermove event is triggered. Only one infotip element per mapview is valid. The current infotip will be cleared before a new element is created. A falsy argument (eg. null) will simply clear the infotip without creating a new element. The pointermove event will be unset when the current infotip element is cleared.
mapview.locate will draw an icon on the browser navigator position retrieved from mapp.utils.getCurrentPosition. The icon will be removed from the mapview.Map if mapview.locate is called again.
The infotip method creates a .popup
element with params.content provided as HTML element. Unlike the infotip element, the popup element has a static position. The position can be provided as params.coords. Otherwise the element is on the current mapview.position. Only one popup element per mapview is valid. The current popup will be cleared before a new element is created. Providing null as argument will clear the popup element.
The Mapview() decorator method binds interactions as mapview.interactions:{}
.
The current interaction is assigned as mapview.interaction:{}
.
Calling the default method exported from an interaction module will assign the params provided to the interaction defaults as _this
.
The interaction _this
will be set as the current interaction mapview.interaction
after calling the finish method of the current interaction mapview.interaction.finish()
.
Any event listener which are assigned to the mapview.Map and it's target element must be unset when an interaction is finished.
The draw method provides an interface to assign an OL draw interaction to the mapview.Map{} element.
The draw context menu will be assigned to the drawend event of the interaction.
A drawend method can be assigned as params to be executed before the context menu.
An onchange event will be assigned to the draw geometry in the drawstart event of the interaction. The onchange event will execute a tooltip method assigned to the interaction.
The default draw condition is listening for the button of the original event. A right click will remove the most recent vertex of the drawing geometry.
An array of methods assigned as conditions[] will be executed by the draw condition method.
A callback method assigned in the params will be executed by the finish() method.
A snap interaction will be assigned to the mapview if the snap flag is set in the params.
The modify method provides an interface to assign an OL modify interaction to the mapview.Map{} element.
The modify context menu will be assigned to the modifyend event of the interaction.
Selecting a vertex during the modify interaction will create a popup with the option to remove this vertex.
A callback method assigned in the params will be executed by the finish() method.
A snap interaction will be assigned to the mapview if the snap flag is set in the params.
The OL snap interaction will be set on the mapview in addition to a draw or modify interaction if the params for either interaction has a snap:true
flag. MVT layer have a snapSource in order for snapping to work with vector tile geometries.
The highlight interaction monitors pointer move, touch, and click events on the mapview. The interaction will visually highlight a map feature at the pointer pixel location and get the associated location for the feature on the pointer click event.
mapview.Map.forEachFeatureAtPixel() will find a Set of candidate features within the hitTolerance that pass the layerFilter. If not specified in the params, the default layerFilter() will look at all mapview.layers:{}
which have a qID
. The pointerMove event will check whether the Set of features changes. The top most feature from a changed Set will be passed to interaction.highlight()
. A string noChange
will be provided if the Set of candidate features is unchanged during the pointerMove event.
The default highlight() method will assign the highlighted feature as interaction.current:{}
. The feature id is assigned as layer.highlight
. The default interaction.highlight method will return without further action if the original pointer event is 'touch'. If defined as a function layer.hover() will be called with the highlight feature as argument. A highlight flag and the style will be set on the feature if supported. Otherwise the changed() event will be called on the Openlayers layer.L:{}
forcing a re-render of the layer canvas. The render will check whether the highlight ID on the layer matches a feature ID to determine whether a highlight style should be applied to the feature.
The clear() method removes the interaction.current:{}
assignment and resets the styling of associated feature and layer.
The singleClick() event method will emulate a pointerMove() event to determine which feature should be highlighted. The getLocation() method is called from the singleClick event. The default getLocation() method which is called from the singleClick will call mapp.location.get() with properties from the current highlight feature. mapp.location.nnearest() will be called if the feature consists of multiple locations.
The zoom interaction will draw a temporary rectangular polygon. The mapview.Map view[port] will be set to fit the extent of the drawn zoombox.
A Mapp Layer is an interface for spatial data. Layer are defined as JSON objects in the layers array of a Workspace Locale. A valid layer must have a format and a data source connection (dbs) defined. The XYZ host will assign defaults to a layer object.
A mapview must be assigned to the layer object in order to decorate a layer.
The layer decorator passes the layer to a defined format method which assigns the Openlayers layer object (L).
Common interface methods such as layer.show, and hide are assigned to the layer object.
A blank layer.filter object will be set if the filter has not been defined in the JSON layer.
The first theme from the layer.style.themes array will be assigned as layer.style.theme if not already set.
Any plugins matching layer keys will be executed with the layer being passed as argument to the plugin method.
The layer object is returned from the decorator.
The layer's display property will be set to true.
The OL layer layer.L will be removed first and then add to the mapview.map control. This is to prevent that the layer.L is added more than once to the map control.
A displayTrue
event will be dispatched to the layer's view.
The layer's attribition will be added to the mapview.
An URL parameter hook is added if enabled for the mapview.
The layer's display property will be set to false.
The OL layer layer.L will be removed from the mapview.map control.
A displayFalse
event will be dispatched to the layer's view.
The layer's attribition will be removed from the mapview.
An URL parameter hook is removed if enabled for the mapview.
Return layer table value for the current zoom level. Will return the first or last table (maybe null) if the current zoom level exceeds the range defined in layer.tables.
Return the last table value from the layer.tables object which is not null.
Return the first table value from the layer.tables object which is not null.
mapp.layers.format{} is a collection of methods to create an Openlayers' layer and source from the JSON layer configuration when the Mapp layer is decorated.
The layer.format.cluster assigns an OL vector layer and source in the mapp.layer.decorate method. The cluster loader method is triggered from the mapview.Map changeEnd event. The loader method sends an XHR to the mapview.host with parameters inferred from the current viewport and style configuration. The loader method will create OL features from projected coordinates in the cluster response. A new OL vector source with the features will be assigned to the vector layer, effectively removing the existing source and features. The current max value will be calculated from the cluster response and assigned to the layer in order to calculate the cluster icon scale. Setting the vector source on the existing vector layer will automatically trigger the assigned layer.style method.
GeoJSON format layer request data from the GeoJSON API.
Features are not requested on viewport changes but only through the layer.reload() method.
The GeoJSON API will build the feature properties as JSON from the layer.properties{}
entries.
The layer.clusterSource{}
entry can be used to cluster GeoJSON point features according to the distance in pixel.
"format": "geojson",
// host database connection
"dbs": "DEV",
// schema.table for the database connection
"table": "dev.bristol_sentiment",
// geometry field name in table
"geom": "geom_4326",
// geometry projection, default: 4326
"srid": "4326",
// geojson feature properties
"properties": {
"sentiment": "sentiment"
},
// use Openlayers cluster source
"clusterSource": {
// distance between cluster features in pixel.
"distance": 100
},
mapp.layer.Style() returns a style method which can be assigned to an Openlayers layer object. The Openlayers render process will iterate through the layer features and pass each as argument to the style method which returns an Openlayers style object for the renderer.
The style method is assigned by the mapp.layer.format{} method when a Mapp layer object is decorated. A custom style method can be assigned to the layer with the function as argument in layer.L.setStyle()
.
Openlayers style functions must be synchronous.
Processing of a feature in the mapp.layer.Style() method can broken down into these steps.
-
The feature.properties{} are assigned as properties to the feature object.
-
The feature.property.count is assigned from the length of the getFeatures() array for features on cluster format layers.
-
A check is made whether the feature exists in the layer.featureLookup[] array. The feature is not styled if a featureLookup array is configured but the feature is not referenced in the array. Otherwise the properties from the featureLookup entry are assigned to the feature.properties{}.
-
The feature.style{} is assigned from the layer.style.default{}.
-
The layer.style.cluster{} is assigned to the feature.style{} for features with properties.count of more than 1.
-
Assign layer.style.theme.style{} to the feature.style{}.
-
Assign feature.geometryType from the feature geometry type.
-
Assign feature.style.icon for Point geometry features.
-
Pass feature as argument to mapp.layer.themes{} method.
-
Apply cluster, zoomIn, and zoomOut scales.
The clusterScale is applied to the style.icon. The clusterScale is the icon scale for the cluster with the largest size. The size is either the count of locations in a cluster or the aggregate sum of field.values for all locations grouped in a cluster. Scaling is either linear or logarithmic (logScale
) between the smallest (or single location) and largest cluster.
zoomInScale and zoomOutScale are applied to icon styles based on the current zoom level.
-
layer.style.highlight is assigned to feature.style on a feature whose ID is found in layer.highlight[] array.
-
layer.style.label is assigned to feature.style if the layer.style.label.display is true and the current zoom does not exceed the min and max zoom range defined in layer.style.label.
-
layer.style.selected is assigned to features which are referenced in the mapview.locations{} proxy.
An OL style is returned to the layer render method. The OL style is returned from utils.style() which receives the JSON style and feature as arguments.
The JSON layer.style{} allows for the configuration of a single theme{} or a themes{} lookup object. The first key-value from the themes{} lookup will be assigned as the theme{} in the layer decorator.
The theme method referenced by the type key-value will be called with the JSON theme and feature as arguments. It is possible to assign custom themes to mapp.layer.themes{} with a plugin. The custom logic allows for a style to be assigned to the feature according to the features properties provided by the feature layer source.
The categorized theme method will use the field key-value as feature property lookup of a style in the cat{} object.
The distributed theme attempts to evenly distribute styles from the cat_arr[]. The method attempts to not assign the same style to features with intersecting bounding boxes.
The graduated theme method will iterate through the cat_arr[]. The style from the array entry where the value range matches the field feature property is returned.
Locations are functional mapp objects. Locations are not selected but need to have a layer assigned in order to get the location data from the location/get API. The schema for location data is configured as an array of entries layer.infoj[] in the workspace.
A location object with a layer and id value must be provided to the mapp.location.get() method. A request will be sent to the location/get API. The response from the request will populate the entry values in the location.infoj[] array.
The location.infoj[] array holds entry objects for the location as configured in the JSON layer.infoj[] in the workspace.
mapp.location.decorate() will assign location methods and callback arrays to the location object passed as argument.
The location.flyTo() method will fit the view of the location.layer.mapviev{} to the extent of all features in all OL layers in the location.Layers[] array.
The OL layer objects for geometries associated to a location are stored in the location.Layers[] array.
The location.remove() method will remove all location.Layers[] from the location.layer.mapview{} and set the highlight interaction on the mapview. This is to ensure that any interaction initiated from a location entry is finished. An instanceof HTMLElement assigned as layer.view will be removed from the document. The location.hook will be filtered from the URL locations parameter and the location.layer.mapview.locations{} list object. The location.layer will be redrawn after a location is removed. Finally each method from the location.removeCallbacks[] array will be called.
If confirmed the location will be removed from the datasource first by sending the location details to the location/delete API. Thereafter the location.remove() method will be called.
The location.update() method will send a post request to the location/update API. The request body contains a filtered location.infoj array with only the entries which have values as newValue assigned. After a successful update the method will query all dependent entry fields and call all methods from the location.updateCallbacks[] array.
Checks whether two Sets are equal.
(a, b) => a.size === b.size && [...a].every(value => b.has(value))
The module will dynamically import the convert library from skypack. The value provided as first argument will be converted and dressed according to the params argument.
params = {
units: 'meter',
convertTo: 'miles',
decimals: 0, // default
locale: 'en-GB', // default
prefix: 'Distance: ',
suffix: ' miles',
}
The loadPlugins util take a single or an array of resource locator and attempt to load each as a dynamic module import. The utility will await for all dynamic imports to resolve.
The merge util assigns values from source objects to the target object. Matching target key values will be overwritten. A deep merge is performed by recursive iteration through the object.
The promiseAll util takes an array of promises and resolves once all promises have been resolved.
The style utility method receives a JSON style object, and an OL feature as optional argument and returns an OL style object. The OL style is created from stroke, fill, image(icon), and text(label) OL style objects.
svgSymbols is a collection of methods which return encoded and serialized SVG from a parameterized request.
The methods are:
- dot
- target
- triangle
- square
- diamond
- semiCircle
- markerLetter
- markerColor
- circle
- template
The xhr util wrap an XMLHttpRequest in a promise. Requests can be provided as a params object. Supported parameter are:
- url: The request URL.
- responseType: The requests response type, defaults to
json
. - body: A post request will be made a body is provided.
- cache: The response will be cached in a Map collection.
- requestHeader: An object with key/values representing the requestHeader sent with the request.
Provided as a string the method argument will evaluated as the URL param.
URL parameter can be inspected and set with the hooks module. Upon initialisation of the mapp module, URL parameter are parsed and stored in the mapp.hooks.current object.