Overlay layer for markers and highlights

Quick start

The example below, running in the Mappia calculator - click it to run it live. Full-size picture

  1. Run it

    Click the picture: the map opens right here and runs the example. Nothing is saved, and nothing to install.

  2. Try it
    • Find the red dot over Belo Horizonte: the overlay draws it once the map has loaded.
    • Look at the layer panel: only States is listed - the dot has no row and no switch.
    • Change the coordinates in createPoint and run it again: the dot moves to the new place.
  3. Make it yours

    Copy the query, change it - the key parameters are below - and run it again in the playground, or paste it into the Mappia editor to save it as your map.

Key parameters

ParameterExampleWhat it does
LayerAdditionalnew Ext.LayerAdditional({}, ExtjsUtils.JS.getMap())Creates the overlay on the map. Create it once and reuse it for every marker.
createPointoverlay.createPoint(-43.94, -19.92, "EPSG:4326")A point from coordinates in the projection you name, converted to the map’s. Longitude comes first.
createFeatureoverlay.createFeature(point)Wraps a geometry, or an array of them, into a feature you can style and draw.
drawFeatureoverlay.drawFeature(city, { fillColor: "#e74c3c", fillOpacity: 1, pointRadius: 11 })Styles and draws a feature in one call. Without fillOpacity: 1 the fill stays translucent.
removeFeaturesoverlay.removeFeatures()Clears the overlay. With no argument every feature is removed; pass features to remove only those.

Every parameter, with its type and default, is in the reference at the end of this page.

Complete example

The query 11 lines · runs as is
// Overlay layer: Ext.LayerAdditional draws markers and highlights without adding a row to the
// layer panel. runNow is the one global the platform calls itself, once, after loading.
ExtjsUtils.QUERY.setQueryGlobalProperties({
  runNow: function () {
    var overlay = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap());
    var city = overlay.createFeature(overlay.createPoint(-43.94, -19.92, "EPSG:4326")); // Belo Horizonte
    overlay.drawFeature(city, { graphicName: "circle", pointRadius: 11, fillColor: "#e74c3c", fillOpacity: 1, strokeColor: "#ffffff", strokeWidth: 3 });
  },
}) && [
  { name: "CSR:estados", title: "States", visibility: true, opacity: 0.4 },
];

Customize it

Run it once the map is ready

The overlay needs the map, so create it in code that runs after loading. runNow is the one global the platform calls by itself, once, after the query loads; declare it with ExtjsUtils.QUERY.setQueryGlobalProperties, as the example does. A button handler, a click callback or a message from the page that embeds the map (MappiaIO) work too.

Keep one overlay and redraw it

To move a marker, clear the overlay and draw again. Keep the overlay in a query global so every call reuses it:

ExtjsUtils.QUERY.setQueryGlobalProperties({
  spotOverlay: null,
  markSpot: function (lon, lat) {
    if (!window.spotOverlay) window.spotOverlay = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap());
    var overlay = window.spotOverlay;
    overlay.removeFeatures();                                  // clear the previous marker
    var spot = overlay.createFeature(overlay.createPoint(lon, lat, "EPSG:4326"));
    overlay.drawFeature(spot, { graphicName: "circle", pointRadius: 9, fillColor: "#e74c3c",
      fillOpacity: 1, strokeColor: "#ffffff", strokeWidth: 2 });
  },
}) && [{ name: "CSR:estados", title: "States", visibility: true }];

Then any callback can call window.markSpot(-43.94, -19.92).

More than points

  • createPolygon([p1, p2, p3]) makes a polygon from points made with createPoint; the ring closes by itself.
  • drawLatLongExtents([west, south, east, north], color) outlines a longitude/latitude box, the way the interface highlights a layer’s extent.
  • GeoJSON goes in with overlay.addFeatures(ExtjsUtils.GEOJSON.geojson2Features(geojson, "EPSG:4326")). Name the projection: without it the data is read as Web Mercator metres and lands in the wrong place.

Style

drawFeature takes OpenLayers style properties: fillColor, fillOpacity, strokeColor, strokeWidth, pointRadius, graphicName ("circle", "square", "star"…), externalGraphic (an image URL) and label. Features added with addFeatures use the overlay’s own style instead: a plain grey and white one, unless you create the overlay first with overlay.createLayer({ styleMap: new OpenLayers.StyleMap({...}) }).

Show, hide and remove

The overlay does not follow any other layer: overlay.setVisibility(false) hides it and setVisibility(true) shows it again. removeLayer() takes it off the map entirely.

When to use a file layer instead

The overlay is deliberately invisible to the layer panel: the user cannot turn it off, and it has no click callbacks of its own. For data the user should see listed, switch on and off and click, use a file layer.

Reference: every parameter

Generated from the platform source. Every entry, searchable, is in the API reference; the raw data is api.json. Open an entry for its description, parameters and example; # links to it.

Ext.LayerAdditional · overlay layer built from code

LayerAdditional16 entries
A private vector layer kept out of the layer tree, for markers, highlights and geometry pushed from the parent page.
Usage: var overlay = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap()); overlay.createLayer(); overlay.addFeatures(features);
View the complete LayerAdditional API here.

LayerAdditional

function(config, map)# new Ext.LayerAdditional(config, map) — a private vector overlay: an OpenLayers.Layer.Vector that is added to the map but deliberately kept out of the layer tree (displayInLayerSwitcher: false), …

Written as Ext.LayerAdditional

new Ext.LayerAdditional(config, map) — a private vector overlay: an OpenLayers.Layer.Vector that is added to the map but deliberately kept out of the layer tree (displayInLayerSwitcher: false), for markers, highlights, search results and geometry pushed in from a parent page. Use it when something must render on the map without becoming a user-visible, toggleable tree entry; for ordinary user-facing data prefer a declarative source: "file" layer. The backing layer is created lazily by createLayer() (or by drawFeature()), and features added before that are buffered and flushed on creation. It does not follow the visibility of any other layer on its own.

Constructor arguments: config — an object with the optional keys listeners (an Ext listeners object for the events below) and layerConfig (when given, the layer is created immediately with createLayer(layerConfig, layerConfig.async)); map — the OpenLayers.Map to draw on, normally ExtjsUtils.JS.getMap() / app.mapPanel.map.

Events (Ext.util.Observable): addedLayer — fired with {layer} right after the vector layer is created and added to the map; removedLayer — fired with {layer} by removeLayer() right after the layer is removed from the map.

Public properties: vectorLayer — the OpenLayers.Layer.Vector, null until created; map — the map given to the constructor.

config Object
Optional configuration: listeners and/or layerConfig as described above; pass {} for none.
map OpenLayers.Map
The map the overlay is drawn on.
// a reusable highlight overlay driven by parent-page messages
ExtjsUtils.QUERY.setQueryGlobalProperties({
    highlightLayer: null,
    ensureHighlightLayer: function() {
        if (!window.highlightLayer) {
            window.highlightLayer = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap());
            window.highlightLayer.createLayer({
                styleMap: new OpenLayers.StyleMap({
                    "default": new OpenLayers.Style({fillColor: "#ffcc33", fillOpacity: 0.35, strokeColor: "#ff6600", strokeWidth: 2, pointRadius: 6, graphicName: "circle"})
                })
            });
        }
        return window.highlightLayer;
    },
    showHighlight: function(geojson) {
        var overlay = window.ensureHighlightLayer();
        overlay.removeFeatures(); // no argument: clear everything
        overlay.addFeatures(ExtjsUtils.GEOJSON.geojson2Features(geojson));
    }
}) && ExtjsUtils.QUERY.setMappiaIoCallback(function(message) {
    if (message && message.type === "geojson") window.showHighlight(message.msg);
}) && [
    { name: "CSR:estados", title: "Estados", visibility: true }
]
// listen to the layer lifecycle
var overlay = new Ext.LayerAdditional({
    listeners: { addedLayer: function(evt) { console.log("created", evt.layer.id); } }
}, ExtjsUtils.JS.getMap());

addFeatures

function(features)# Adds one feature or an array of features to the overlay.

Adds one feature or an array of features to the overlay. When the layer does not exist yet the features are buffered and added as soon as createLayer runs, so it is safe to call in any order. Features must be in the map projection — build them with createPoint/createFeature, or convert GeoJSON with ExtjsUtils.GEOJSON.geojson2Features.

features OpenLayers.Feature.Vector|Array.<OpenLayers.Feature.Vector>
The feature(s) to add.
overlay.addFeatures(new OpenLayers.Feature.Vector(overlay.createPoint(-44.0, -20.5, "EPSG:4326"), {name: "Fazenda"}));

createFeature

function(geometries) : OpenLayers.Feature.Vector# Wraps one geometry, or an array of geometries (combined into an OpenLayers.Geometry.Collection), in a vector feature you can then style and add with drawFeature/addFeatures.

Wraps one geometry, or an array of geometries (combined into an OpenLayers.Geometry.Collection), in a vector feature you can then style and add with drawFeature/addFeatures.

geometries OpenLayers.Geometry|Array.<OpenLayers.Geometry>
The geometry, or several geometries drawn as one feature.

Returns The new feature (no attributes, no style).

var feature = overlay.createFeature(overlay.createPoint(-44.0, -20.5, "EPSG:4326"));
feature.attributes.name = "Fazenda";
overlay.addFeatures(feature);

createImageTile

function(bbox, projection) : OpenLayers.Feature.Vector|undefined# Builds a feature representing an image tile: a rectangle covering bbox plus a point at its centre, combined in one geometry collection.

Builds a feature representing an image tile: a rectangle covering bbox plus a point at its centre, combined in one geometry collection. Style it with externalGraphic (the image URL) and pointRadius (half the image size) to draw a picture at the centre of the box, e.g. a thumbnail or a symbol over an area. Returns undefined (and logs) when bbox does not have exactly four numbers.

bbox Array.<Number>
The tile bounds as [left, bottom, right, top].
projection String|OpenLayers.Projection
The projection bbox is expressed in.

Returns The tile feature, or undefined for an invalid bbox.

var tile = overlay.createImageTile([-44.1, -20.6, -43.9, -20.4], "EPSG:4326");
overlay.drawFeature(tile, {externalGraphic: "/theme/app/img/logo.png", pointRadius: 24, strokeColor: "#666666", fillOpacity: 0});

createLayer

function(layerConfig, async)# Creates the backing vector layer, once: the call is ignored when the layer already exists or its creation is pending, and the configuration of an existing layer is not updated.

Creates the backing vector layer, once: the call is ignored when the layer already exists or its creation is pending, and the configuration of an existing layer is not updated. The layer gets a generated id, displayInLayerSwitcher: false and the initialVisibility, is added to the map, addedLayer is fired and the features buffered by addFeatures are flushed into it. When layerConfig is omitted a built-in grey/white styleMap for points, lines and polygons is used. Creation is synchronous by default; pass async: true to defer it to a short timeout (useful when called from inside another map event).

layerConfig Object
OpenLayers.Layer.Vector options — typically {styleMap: new OpenLayers.StyleMap({...})}; omitted ⇒ the default style.
async Boolean
true to create the layer asynchronously (via setTimeout); false, the default, creates it immediately.
var overlay = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap());
overlay.createLayer({
    styleMap: new OpenLayers.StyleMap({
        "default": new OpenLayers.Style({fillColor: "${color}", fillOpacity: 0.4, strokeColor: "#333333", strokeWidth: 1}),
        "select": new OpenLayers.Style({strokeColor: "#ff0000", strokeWidth: 3})
    })
});

createPoint

function(x, y, projection) : OpenLayers.Geometry.Point# Creates a point geometry from coordinates given in projection and transforms it into the map projection, ready to be wrapped in a feature or used as a polygon vertex.

Creates a point geometry from coordinates given in projection and transforms it into the map projection, ready to be wrapped in a feature or used as a polygon vertex. For a longitude/latitude pair pass "EPSG:4326".

x Number
The horizontal coordinate (longitude for EPSG:4326).
y Number
The vertical coordinate (latitude for EPSG:4326).
projection String|OpenLayers.Projection
The projection x/y are expressed in (see resolveProjection).

Returns The point, in the map projection.

var marker = new OpenLayers.Feature.Vector(overlay.createPoint(-46.63, -23.55, "EPSG:4326"));
overlay.addFeatures(marker);

createPolygon

function(points) : OpenLayers.Geometry.Polygon# Creates a polygon geometry with a single ring whose vertices are the given points (in order; the ring is closed automatically).

Creates a polygon geometry with a single ring whose vertices are the given points (in order; the ring is closed automatically).

points Array.<OpenLayers.Geometry.Point>
The vertices, already in the map projection (e.g. from createPoint).

Returns The polygon.

var square = overlay.createPolygon([
    overlay.createPoint(-44.1, -20.4, "EPSG:4326"), overlay.createPoint(-43.9, -20.4, "EPSG:4326"),
    overlay.createPoint(-43.9, -20.6, "EPSG:4326"), overlay.createPoint(-44.1, -20.6, "EPSG:4326")
]);
overlay.drawFeature(overlay.createFeature(square), {fillColor: "#00ff00", fillOpacity: 0.2});

drawFeature

function(feature, style)# Styles and draws a feature in one call: creates the layer if needed (createLayer() with the default style), sets feature.style to style completed with OpenLayers' default symbolizer, and adds the feature.

Styles and draws a feature in one call: creates the layer if needed (createLayer() with the default style), sets feature.style to style completed with OpenLayers' default symbolizer, and adds the feature. A per-feature style set this way takes precedence over the layer's styleMap.

feature OpenLayers.Feature.Vector
The feature to draw (see createFeature).
style Object
OpenLayers symbolizer properties (fillColor, fillOpacity, strokeColor, strokeWidth, pointRadius, externalGraphic, label, ...); omitted ⇒ the layer's styleMap applies.
var point = overlay.createFeature(overlay.createPoint(-44.0, -20.5, "EPSG:4326"));
overlay.drawFeature(point, {pointRadius: 8, fillColor: "#ff0000", strokeColor: "#ffffff", strokeWidth: 2});

drawLatLongExtents

function(llbbox, color)# Draws a highlighted rectangle for a lon/lat bounding box — the way the interface outlines a layer's extent: two stacked rectangles, a wide white border with a translucent fill under a thin coloured border.

Draws a highlighted rectangle for a lon/lat bounding box — the way the interface outlines a layer's extent: two stacked rectangles, a wide white border with a translucent fill under a thin coloured border. Creates the layer if needed. Logs and does nothing when llbbox does not have exactly four numbers.

llbbox Array.<Number>
The bounds in EPSG:4326 as [left, bottom, right, top] (west, south, east, north), e.g. a record's llbbox.
color String
Fill colour (and, by default, the thin border colour #FFC000 is used).
var record = ExtjsUtils.LAYER.getLayersRecord("CSR:estados");
overlay.drawLatLongExtents(record.get("llbbox"), "#ff8800");

map

OpenLayers.Map# The OpenLayers.Map the overlay draws on, as given to the constructor.

The OpenLayers.Map the overlay draws on, as given to the constructor.

removeFeatures

function(features)# Removes features from the overlay — the given feature or array of features, or every feature when the argument is omitted (the usual "clear the highlight" call).

Removes features from the overlay — the given feature or array of features, or every feature when the argument is omitted (the usual "clear the highlight" call). Works before the layer exists too, by dropping them from the pending buffer.

features OpenLayers.Feature.Vector|Array.<OpenLayers.Feature.Vector>
The feature(s) to remove; omit to remove all.
overlay.removeFeatures();            // clear everything
overlay.removeFeatures(oneFeature);  // remove a single feature

removeLayer

function()# Removes the vector layer from the map (firing removedLayer), cancels a pending async creation and forgets the layer, so the next createLayer/drawFeature creates a fresh one.

Removes the vector layer from the map (firing removedLayer), cancels a pending async creation and forgets the layer, so the next createLayer/drawFeature creates a fresh one. To only clear the drawn features and keep the layer, use removeFeatures() instead.

overlay.removeLayer();

resolveProjection

function(projection) : OpenLayers.Projection# Normalizes a projection given as an EPSG string ("EPSG:4326"), an OpenLayers.Projection or any object with getCode() into an OpenLayers.Projection, falling back to the map projection when it is missing.

Normalizes a projection given as an EPSG string ("EPSG:4326"), an OpenLayers.Projection or any object with getCode() into an OpenLayers.Projection, falling back to the map projection when it is missing. Delegates to ExtjsUtils.PROJECTION.resolveProjectionObject; createPoint uses it, so you rarely need to call it yourself.

projection String|OpenLayers.Projection|Object
The projection to resolve; falsy ⇒ the map projection.

Returns The resolved projection object.

var proj = overlay.resolveProjection("EPSG:4326");
console.log(proj.getCode()); // "EPSG:4326"

setOverLayer

function(baseLayer)# Makes sure the overlay is stacked above baseLayer: moves the vector layer's index to at least that layer's index (map.setLayerIndex).

Makes sure the overlay is stacked above baseLayer: moves the vector layer's index to at least that layer's index (map.setLayerIndex). Call it after createLayer (or after starting an async creation); the reorder happens on a short timeout to work around an OpenLayers/Ext re-entrancy bug when called from inside an event, so it is not effective synchronously.

baseLayer OpenLayers.Layer
The layer that must end up below the overlay.
overlay.createLayer();
overlay.setOverLayer(ExtjsUtils.LAYER.getLayerByName("CSR:estados"));

setVisibility

function(state)# Shows or hides the overlay.

Shows or hides the overlay. Before the layer is created it only records the initial visibility the layer will be created with; afterwards it calls vectorLayer.setVisibility(state).

state Boolean
true to show the overlay, false to hide it.
overlay.setVisibility(!MOBILE_UTILS.isMobile());

vectorLayer

OpenLayers.Layer.Vector|null# The backing OpenLayers.Layer.Vector where the features are drawn.

The backing OpenLayers.Layer.Vector where the features are drawn. null until createLayer runs, then a real OpenLayers vector layer you may hand to other controls, e.g. new OpenLayers.Control.CustomSelectFeature(overlay.vectorLayer, {...}).

overlay.createLayer();
overlay.vectorLayer.events.register("featureselected", null, function(evt) { console.log(evt.feature); });