It should already be part of 8.1.14. Although, you’ll want the latest nightly that fixed a regression related to missing position properties in vector and marker click events. We also added some other features we hope you’ll find useful.
Summary of changes:
The configuration possibilities of the Map components GeoJSON layers has been expanded to allow style options for GeoJSON feature objects. A feature object has a “type” property with a value of “Feature”. If you wish to familiarize yourself with the GeoJSON schema specifications, you can find them here.
The default schema of Polygon, Polyline, Rectangle, and Circle layers has been changed to align with how GeoJSON features are configured, and to help make configuration more straight forward.
The vector and marker click events now get passed a dictionary parameter called “properties”.
GeoJSON layer
-
A
styleOptions
property can be added to configure style related options of feature objects- Add
styleOptions
at the layer level for shared style options among features - Add
styleOptions
at the feature level to override any shared style options, and apply feature specific style options
styleOptions: { "stroke": true, "color": "", "weight": 1, "opacity": 1, "lineCap": "inherit", "lineJoin": "inherit", "dashArray": "", "dashOffset": "", "fill": true, "fillColor": "", "fillOpacity": 1, "fillRule": "inherit", "interactive": true }
- Add
-
GeoJSON feature objects that are rendered on the map are subscribed to click events, triggering vector and marker click events
-
The
properties
member object of a feature object is a supplied parameter to vector and marker clicked event handlers -
Point
feature objects, which Leaflet renders as markers by default, accept special configuration-
May be rendered as a
circle
marker oricon
marker based upon the value of the feature object’srender
propertymarker: { render: "circle" }
-
May be configured to show a basic text tooltip, with various options equivalent to Leaflet’s tooltip options here
marker: { tooltip: { content: { text: "Forest Products Laboratory" }, options: { direction: "auto", permanent: false, sticky: true, interactive: false, opacity: 0.9, className: "" } } }
-
May be configured to show a basic text popup, with various options equivalent to Leaflet’s popup options here
marker: { popup: { content: { text: "1 Gifford Pinchot Drive" }, options: { maxWidth: 300, minWidth: 50, maxHeight: null, autoPan: true, keepInView: false, autoClose: true, closeOnEscapeKey: true, className: "" } } }
-
Can be configured even further with marker specific options, mostly equivalent to Leaflet’s marker and circle marker options here
marker: { options: { opacity: 1, riseOffset: 0, riseOnHover: false, draggable: false, clickable: true, radius: 10 } }
-
The Map components GeoJSON layers are not meant to be modified directly via the property editor. It is the expectation that designers will make use of an HTTP binding and a map transform to add these configurations as foreign members (object member properties not part of the GeoJSON schema spec) to their layers and features that we process and pass along to the Leaflet API. Here is an example of a map transform on the returned response of an HTTP binding:
```
def transform(self, value, quality, timestamp):
from com.inductiveautomation.ignition.common.script.adapters import PyJsonObjectAdapter
from org.python.core import PyArray
# This function is how the Map component and Leaflet traverses and determines if an GeoJSON object qualifies as a Feature object. It is generic. If you know
# what the layer looks like, i.e. a FeatureCollection of Point objects, you definitely don't need this.
def walkFeatures(geojson, operate):
features = geojson if isinstance(geojson, PyArray) else geojson['features'] if isinstance(geojson, PyJsonObjectAdapter) and isinstance(geojson['features'], PyArray) else None
if features:
for idx in range(len(features)):
feature = features[idx]
if isinstance(feature, PyJsonObjectAdapter):
if feature.has_key('features'):
walkFeatures(feature['features'], operate)
elif feature.has_key('geometry') or feature.has_key('geometries') or feature.has_key('coordinates'):
operate(feature)
elif isinstance(geojson, PyJsonObjectAdapter):
if feature.has_key('geometry') or feature.has_key('geometries') or feature.has_key('coordinates'):
operate(geojson)
# Operates on a feature, in this example, all of the features of this layer are expected to be Point objects, which we configure as Leaflet markers
def operateOnFeature(feature):
if isinstance(feature, PyJsonObjectAdapter):
marker = {
'render': 'icon',
'icon': {
'path': 'material/location_on',
'size': {
'width': 36,
'height': 36
},
'color': '#9bfa03'
}
}
if feature.has_key('properties'):
properties = feature['properties']
LOCATION_TYPE = properties.get('LOCATION_TYPE')
LOCATION_NAME = properties.get('LOCATION_NAME')
ADDRESS_LINE1 = properties.get('ADDRESS_LINE1')
if LOCATION_TYPE == 'Headquarters':
marker['icon']['color'] = '#ff0000'
marker['tooltip'] = {
'content': {
'text': LOCATION_NAME
}
}
marker['popup'] = {
'content': {
'text': properties
}
}
feature['marker'] = marker
walkFeatures(value, operateOnFeature)
return value
```
Polygon, Polyline, Rectangle, and Circle layers
-
The default schema of vector Polygon and Polyline objects has been altered to allow specifying a
name
andproperties
property which is supplied as a parameter to click event handlers. Previous schema shapes are still accepted. For example,Old default schema shape:
polyline: [ // An array of polyline layers { // A single layer of polylines polylines: [ // Polylines belonging to this single layer [ // A polyline, defined by an array of points { // A single point of this polyline, requires min of two points lat: null, lng: null } ] ] } ]
New default schema shape:
polyline: [ // An array of polyline layers { // A single layer of polylines polylines: [ // Polylines belonging to this single layer { name: "", // The name of this polyline properties: { // Properties of this polyline }, points: [ // An array of points { // A single point of this polyline, requires min of two points lat: null, lng: null } ] } ] } ]
-
name
andproperties
properties where added tocircle
andrectangle
vector schemas -
The
name
property which existed at the layer level of vector objects has been hidden from the schema, in exchange for individual object level specifying ofname
(see above). To prevent regression, the name that was defined on the layer will be used if the name defined on the vector object is empty or undefined.
To create a basic GeoJSON layer, you can use this mapping tool.
For real world example datasets, see data.gov. Beware, these datasets can be quite large.
Other changes
-
We now supply the true lat, lng coordinates of an element when a vector or marker is clicked. The true coordinates are derived directly from click event data, instead of being initialized from configuration. The change is a result of realizing that it is possible to make a marker draggable through configuration, and as such initializing coordinates from configuration would present incorrect data.
-
Configuration of objects is now more flexible. Any additional configuration is merged and forwarded directly to the Leaflet API. This is an advanced feature, so use with care. Its purpose is to prevent having to submit a request for a property listed in the API, on say, a marker object, and block a designer’s work until that feature is finally added. For example: on a marker object you should be able to make a marker draggable by simply adding the draggable property and setting it to true, as outlined in the Leaflet documentation.
-
Changes to the configuration of a GeoJSON layer will result in that layer being redrawn. We detect changes by performing a deep equality comparison on current layers and previous layers. An approach mostly unique to GeoJSON layers only. Leaflet is a low level JS library, and as such requires some arm twisting to work nicely with React.