Hoverpixel

Markup: {{hoverpixel}}

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
    • Move the cursor over the map: a notification shows the elevation in metres and the position in degrees.
    • Turn off “Show the elevation under the cursor” in the layer panel to stop the readings.
  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.

  4. More ways to use it

Key parameters

ParameterExampleWhat it does
runOnHoveronHoverName of a function in functions, called on every mouse move with (layerVals, inputs, coordinates, event, lastInfo); this is the layer.
runOnClickonMapClickThe same, but called only when the user clicks the map.
checkedtrueStart with the tool switched on. By default the user switches it on in the layer panel.
runOnHoverOutsidetrueAlso call runOnHover where the map has no data; layerVals is then null. runOnClickOutside does the same for clicks.
textShow the elevation under the cursorLabel of the switch in the layer panel.
idelevation_hoverNames the tool: inputs.id["elevation_hover"] holds the last click and hover positions, in degrees.

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

Complete example

The query 25 lines · runs as is
// Hoverpixel: reads the value of each map under the cursor and passes it to runOnHover
// (layerVals, inputs, coordinates); this = the layer.
[
  {
    title: "Elevation under the cursor",
    name: "CSR:altimetria",
    source: "calculate",
    opacity: 0.7,
    visibility: true,
    paramsButtonConfig: [{ type: "query", pressed: true }],
    descriptionHtml:
      "{{hoverpixel|id=elevation_hover|text=Show the elevation under the cursor|checked=true|runOnHover=onHover}}",
    functions: {
      onHover: function (layerVals, inputs, coordinates) {
        // coordinates come in the map's projection (metres): convert them to degrees to show
        var degrees = coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
        ExtjsUtils.ALERTIFY.log("Elevation: <b>" + Math.round(layerVals[0]) + " m</b><br>" +
          degrees.lat.toFixed(2) + ", " + degrees.lon.toFixed(2));
      },
    },
    expression: function (layersVals) {
      return layersVals[0];
    },
  },
];

More examples

Other ways to use Hoverpixel, each a complete query that runs as is - like the one above.

Values in the panel

As the pointer moves, runOnHover writes the values of two maps under it into a label of the panel - here forest biomass and elevation.

Click the picture to run it live. Full-size picture

The query 29 lines · runs as is
// Values in the panel: as the pointer moves, runOnHover writes the values of two maps under it into a label of the panel - here forest biomass and elevation.
// With two maps in name, runOnHover receives both values: layerVals[0] and layerVals[1].
// A place without data comes as an empty value.
[
  {
    title: "Biomass and elevation under the pointer",
    name: "CSR:biomassa_baccini_bioma_am,CSR:altimetria",
    source: "calculate",
    opacity: 0.75,
    visibility: true,
    paramsButtonConfig: [{ type: "query", pressed: true }],
    descriptionHtml:
      "{{hoverpixel|id=readout_hover|text=Read the maps under the pointer|checked=true|hideLabel=true|runOnHover=showValues}}" +
      "{{label|id=readout|text=Move the pointer over the map.}}",
    functions: {
      showValues: function (layerVals) {
        var label = Ext.getCmp("readout");
        if (!label) return;
        function show(value, unit) {
          return value === null || value === undefined || isNaN(value) ? "no data" : Math.round(value) + " " + unit;
        }
        label.setText("Biomass: " + show(layerVals[0], "t/ha") + " - elevation: " + show(layerVals[1], "m"));
      },
    },
    expression: function (layersVals) {
      return layersVals[0]; // the map shows the biomass
    },
  },
];

Customize it

What the callback receives

  • layerVals: one value per map in name, in the same order. When the layer has an expression, one more entry at the end holds its result for that pixel.
  • inputs: the layer’s widget values; inputs.id[ID] works here.
  • coordinates: the position in the map’s projection (metres), despite its lat/lon names. For degrees use coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326")), as the example does.
  • event: the mouse event.
  • lastInfo: {click, hover}, the previous click and hover as {lon, lat} in degrees. The current position is stored only after your callback returns, so use coordinates for it.

Show the value in the panel instead of notifications

A notification on every mouse move gets noisy. Put an element in descriptionHtml and write into it:

descriptionHtml: "{{hoverpixel|id=elevation_hover|checked=true|runOnHover=onHover}}" +
  "<p>Elevation: <b id='elevation_value'>-</b></p>",
functions: {
  onHover: function (layerVals) {
    var target = document.getElementById("elevation_value");
    if (target) target.innerHTML = Math.round(layerVals[0]) + " m";
  },
},

What the values are

The tool reads the colour each map draws under the cursor and turns it into a value through the map’s legend. On a classified map you get the value of the class: a range such as “10 - 20” gives its middle, 15, and a text class stays text. For the original cell values, read a map published as a raw map with an operation such as raw (see the property catalogue).

Recalculating the layer

Moving or clicking never recalculates the layer. inputs.id[ID] is always current, but nothing runs beforeCalc again. React inside runOnHover / runOnClick, which already receive the values, or trigger a recalculation yourself, for example with forceRecalc() on an InputManager.

Pitfalls

  • Outside the map’s data the callbacks are not called, unless you set runOnHoverOutside / runOnClickOutside; then layerVals is null, so check it first.
  • The tool reads the maps of its own layer, a source: "calculate" layer as in the example. It pauses while the layer is hidden and resumes in the same state when it is shown again.
  • unselect only changes the message shown when the tool is switched on; the tool never switches itself off after a click.
  • Write callbacks as regular functions, not arrow functions: this is the layer.

Real maps that use it

Simple Hoverpixel Example

Simple Hoverpixel Example

Simple Hoverpixel Example

Hoverpixel - View pixel value on Hovering

Hoverpixel - View pixel value on Hovering

Total burned area (ha)

Total burned area (ha)

Amazon on focus - Deforestation and fires by land category

Amazon on focus - Deforestation and fires by la...

FIP Cerrado - Fire monitoring (current map)

FIP Cerrado - Fire monitoring (current map)

Panorama of Brazil's Forest Code

Panorama of Brazil's Forest Code

REDD Brazil - Deforestation, emissions and credits

REDD Brazil - Deforestation, emissions and credits

X-ray of the CAR - Forest Code balance per property

X-ray of the CAR - Forest Code balance per prop...

AreaIntegral and SummedArea

AreaIntegral and SummedArea

Reference: the parameters used here

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.

hoverpixel · value under the mouse (input)

Hoverpixel16 entries

Written in a layer's descriptionHtml as {{hoverpixel|parameter=value|...}}

Create a tool to instantly inspect pixel under mouse. The value of the map can also be used as input for another functions.
Usage: {{hoverpixel}}
View the complete HoverPixel API here.

checked

Boolean= false# Defines if the hoverPixel should start enabled.

Defines if the hoverPixel should start enabled. Set true to start enabled, false otherwise.

|checked = true|

fieldLabel

String# Define the text that will be displayed at the left of the toggler

Define the text that will be displayed at the left of the toggler

|text=This is the label text|

getLayerValues

function(evt, layer) : Array.<Number>|null# Reads the values of the composed map under a mouse event: one value per inner layer (from the legend colours of the rendered tiles) plus one extra entry with the result of the layer expression for those values.

Reads the values of the composed map under a mouse event: one value per inner layer (from the legend colours of the rendered tiles) plus one extra entry with the result of the layer expression for those values. This is the layerVals argument of runOnClick/runOnHover; call it from code (Ext.getCmp(id).items.get(0).getLayerValues(evt, layer)) to sample the map from any mouse event. Returns null when the layer is hidden, the legend is not loaded yet, or the mouse is outside the map data (all layers null/transparent).

evt MouseEvent
Mouse event with the screen position to sample.
layer OpenLayers.Layer.Composed
The composed layer to read (normally the tool's own layer).

Returns [value of layer 0, ..., value of layer n-1, expression result], or null.

hideLabel

Boolean= false# Defines if the label of the HoverPixel should be displayed.

Defines if the label of the HoverPixel should be displayed. Set true to hide the label, false to show it.

|hideLabel=true|

iconCls

String= cmn-toggle-icon# Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

|iconCls=my-toggle-icon|

id

String# Defines the id to identify the object.

Defines the id to identify the object.

|id=exemple_hover_pixel|

labelBefore

Boolean= false# Set true to render the text label before (left of) the toggle switch instead of after it.

Set true to render the text label before (left of) the toggle switch instead of after it.

|labelBefore=true|

labelStyle

String# Defines the style of the label at the HoverPixel toggler.

Defines the style of the label at the HoverPixel toggler. You can use CSS to style the label element.

|labelStyle=font-weight: bold; color: red;|

notify

Boolean= true# Set false to suppress the notification shown when the tool is activated ("click on the map...").

Set false to suppress the notification shown when the tool is activated ("click on the map...").

|notify=false|

runOnClick

function= undefined# Defines a callback when the user clicks on the map.

Defines a callback when the user clicks on the map.

It passes the following parameters for the callback function: handleOnClick(layerVals, inputs, coordinates, clickEvent, lastCoordinates)

layerVals Array
Array with the values of the maps at the pixel that was clicked.
inputs Array
Array with the values of the inputs defined in the descriptionHtml.
coordinates OpenLayers.LonLat
The point that was clicked, in the map's projection (Web Mercator, metres) despite the names: lon is x and lat is y. For degrees, transform it: coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326")) (lastCoordinates below already holds degrees, of the previous click and hover).
clickEvent MouseEvent
Mouse event that triggered the function.
lastCoordinates Object
Object with the last coordinates (latitude, longitude) from the last click and the last hover events. lastCoordinates = { click: { lat: // Latitude of the last click lon: // Longitude of the last click }, hover: { lat: // Latitude of the last hover lon: // Longitude of the last hover } }
|handleOnClick: function(layerVals, inputs, coordinates, clickEvent, lastCoordinates) {
     var degrees = coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
     ExtjsUtils.ALERTIFY.log("Latitude: " + degrees.lat.toFixed(3) + " Longitude: " + degrees.lon.toFixed(3));
}|

runOnClickOutside

function# True to run the callback function even when clicking outside of the layer, False to disable.

True to run the callback function even when clicking outside of the layer, False to disable. (Default False)

runOnHover

function= undefined# Defines a callback when the user hovers the map.

Defines a callback when the user hovers the map.

It passes the following parameters for the callback function: handleOnClick(layerVals, inputs, coordinates, clickEvent, lastCoordinates)

layerVals Array
Array with the values of the maps at the pixel that was hovered.
inputs Array
Array with the values of the inputs defined in the descriptionHtml.
coordinates OpenLayers.LonLat
The point that was hovered, in the map's projection (Web Mercator, metres) despite the names: lon is x and lat is y. For degrees, transform it: coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326")) (lastCoordinates below already holds degrees, of the previous click and hover).
mouseMoveEvent MouseEvent
Mouse event that triggered the function.
lastCoordinates Object
Object with the last coordinates (latitude, longitude) from the last click and the last hover events. lastCoordinates = { click: { lat: // Latitude of the last click lon: // Longitude of the last click }, hover: { lat: // Latitude of the last hover lon: // Longitude of the last hover } }
|handleOnHover: function(layerVals, inputs, coordinates, mouseMoveEvent, lastCoordinates) {
     ExtjsUtils.ALERTIFY.log("Latitude: " + coordinates.lat + " Longitude: " + coordinates.lon);
}|

runOnHoverOutside

function# True to run the callback function even when hovering outside of the layer, False to disable.

True to run the callback function even when hovering outside of the layer, False to disable. (Default False)

text

String# Define the text that will be displayed at the right of the toggler

Define the text that will be displayed at the right of the toggler

|text=This is the example text|

unselect

Boolean= true# Only changes the activation message: with the default true it says a single point is expected, with false several.

Only changes the activation message: with the default true it says a single point is expected, with false several. The hoverpixel is never deactivated automatically after a click.

|unselect=false|

value

Object# Value stored in inputs.id[ID]: the lastInfo object {click, hover} with the coordinates ({lon, lat} in EPSG:4326, or null before the first event) of the last click and of the last mouse move …

Value stored in inputs.id[ID]: the lastInfo object {click, hover} with the coordinates ({lon, lat} in EPSG:4326, or null before the first event) of the last click and of the last mouse move while the tool is active. The object is updated in place, so it is always current when read in beforeCalc/expression; it is also the last argument of runOnClick/runOnHover (inside the callback it still holds the previous event — the current one is written right after the callback returns; use the coordinates argument for the current position). The input is registered on the forceupdatelayer event of the widget, which nothing fires by itself — moving the mouse or clicking does not recalculate the layer. React inside runOnClick/runOnHover (which also receive the map values) or trigger the recalculation yourself (e.g. forceRecalc() on an InputManager).

{{hoverpixel|id=hover_tool|text=Inspect values|runOnClick=onMapClick}}
functions: {
    onMapClick: function(layerVals, inputs, coords, evt, lastInfo) {
        console.log(coords, lastInfo.click, inputs.id['hover_tool'] === lastInfo); // current, previous, true
    }
}

TooltipHelper · tooltips

TooltipHelper3 entries
Functions to create tooltips on elements, at fixed positions and at mouse events.
Usage: ExtjsUtils.TooltipHelper
View the complete TooltipHelper API here.

CreateTooltipOnPosition

function(title, contentHtml, position, additionalConfig) : Ext.Tooltiphelper# Create a tooltip at a fixed position.

Written as ExtjsUtils.TooltipHelper.CreateTooltipOnPosition

Create a tooltip at a fixed position.

If the position is the mouse event, the tooltip will be at the right side and below the pointer. If the position is a array[x,y] will anchor the top left at this point.

title String
Tooltip title.
contentHtml String
Tooltip HTML content.
position Event|Array.<Number>
Defines the top left position of the tooltip. Can be either a mouse event at or an array [x:Number, y:Number] with the cursor position.
additionalConfig Object
Additional configuration for the tooltip.

Returns A tooltip anchored at the given position.

CreateTooltipThumb

function(title, description, target, thumbUrl, showDelay) : Ext.ToolTiphelper# Creates a mouse-tracking Ext.ToolTip on a DOM element with a title, a text description (rendered in a <pre>) and an optional thumbnail image.

Written as ExtjsUtils.TooltipHelper.CreateTooltipThumb

Creates a mouse-tracking Ext.ToolTip on a DOM element with a title, a text description (rendered in a <pre>) and an optional thumbnail image. The tooltip ignores mouse events, so it never interferes with the hovered element, and is repositioned by onMoveFixPosition to stay beside the target and inside the viewport. The description is cut at the first sequence of three line breaks.

title String
Tooltip title (may be empty).
description String
Tooltip text.
target HTMLElement
Element that shows the tooltip on hover (the DOM element itself, not an id). Without it the tooltip is created unattached.
thumbUrl String
URL of an image shown above the text.
showDelay Number
Delay in milliseconds before the tooltip appears.

Returns The created tooltip.

var node = document.getElementById("field_area");
ExtjsUtils.TooltipHelper.CreateTooltipThumb("", "Area of the property in hectares.", node);

onMoveFixPosition

function(ttip, x, y)helper# move listener for an Ext.ToolTip that keeps it usable: when the tooltip has a target, it is placed to the left or right of that element (whichever side has room, or the side nearer to the …

Written as ExtjsUtils.TooltipHelper.onMoveFixPosition

move listener for an Ext.ToolTip that keeps it usable: when the tooltip has a target, it is placed to the left or right of that element (whichever side has room, or the side nearer to the mouse), and in any case it is pushed back inside the page when it would overflow the bottom or right edge. CreateTooltipThumb wires it automatically; use it as listeners: {move: ExtjsUtils.TooltipHelper.onMoveFixPosition} on tooltips you build yourself.

ttip Ext.ToolTip
The tooltip being moved.
x Number
New absolute x position of the tooltip (page coordinates).
y Number
New absolute y position of the tooltip (page coordinates).
new Ext.ToolTip({target: node, html: "Details", trackMouse: true,
    listeners: {move: ExtjsUtils.TooltipHelper.onMoveFixPosition}});

Calculated layers: raw maps and operation tokens

RawMaps1 entry
A raw map is published with each pixel's value instead of a colour. A calculated layer reads such a map with operation (raw, sum, average...) to get exact cell values; without operation it gets the value of the map's legend at each pixel. The colours are then applied in the browser.
View the complete Raw Maps API here.

operations

Object# Enumeration of the operations a map of a source: 'calculate' layer can be decoded with.

Enumeration of the operations a map of a source: 'calculate' layer can be decoded with. This is what the operation layer key selects, one token per map in name; the tokens are the lower-case names below, matched case and whitespace insensitive. The values are integers; getFromString(token) and getName(value) convert between the two forms.

  • NORMAL (0, an empty or unknown token): a regular WMS image, each cell is a legend colour/category and not a Raw Map.
  • RAW (1, raw): each resulting cell has the value of the most centred original cell of the aggregated region.
  • RGBA (2, rgba): each resulting cell is an integer packing the RGBA bytes of the pixel (input and output are integers).
  • SUM (3, sum): each resulting cell is the weighted sum of the cells of the covered region, the weight being the covered fraction of each cell (VALUE * COVERED_PERCENTAGE).
  • AVERAGE (4, average): each resulting cell is the weighted mean of the cells of the covered region.
  • MAX (5, max): the greatest cell at least partially covered by the region.
  • MIN (6, min): the smallest cell at least partially covered by the region.
  • INTEGRAL (7, integral): summed-area table, so the sum inside any rectangle is obtained from its four corner cells only.
  • AREAINTEGRAL (8, areaintegral): summed-area table of the covered areas (no further description in the source).
  • AREA (9, area): each cell carries the original map area inside the aggregated region, so totals can be computed at any scale with full precision.
  • CELLS (10, cells): weighted count of the original cells inside the region. Every operation other than NORMAL and RGBA requires the map to be published as a Raw Map that offers it.
LayerWorkerUtils.MapOperations.getFromString('sum'); // 3 (LayerWorkerUtils.MapOperations.SUM)
LayerWorkerUtils.MapOperations.getName(3); // 'SUM'

Layer callbacks: functions you write

LayersFunctions1 entry
Functions you write in a layer and the platform calls: expression, afterCalc and legendColor on calculated layers; beforeCalc, onInputsReady, onVisibilityChange and the functions map on calculated and file layers. Inside them this is the layer - except in expression, see Kinds of layer.

functions

Object= null# Associate custom functions to handle events on layer callbacks such as button callbacks or any layer callbacks.

Associate custom functions to handle events on layer callbacks such as button callbacks or any layer callbacks. These functions are scoped to the Layer and can be referenced by name on layer widget callbacks. Functions can also be accessed using this.functions['<function_name>'].

[
  {
     title: 'Example of functions property',
     color: '#666699',
     elements: [
        {
           title: 'Click the button to see a message',
           name: 'CSR:geologia',
           group: 'Query',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              { 
                 type:'query',
                 pressed: true,
              },
           ],
           descriptionHtml:
              '{{button|id=test_button|text=Click me!|handler=handleTestButtonClick}}',
           functions: {
              handleTestButtonClick: function() {
                 ExtjsUtils.ALERTIFY.log('Button clicked!');
              },
           },
        },
     ],
  },
]