Skip to main content

HTMLMapmlViewerElement

The HTMLMapmlViewerElement interface represents the <mapml-viewer> element.

Properties

Property nameDescription
controlsTurns native map controls on or off. Reflects the controls attribute.
controlsListAllows to change the set of native controls. Reflects the controlslist attribute.
extentReturns the extent of the current map view. Read only.
latGet or set the map's latitude. Reflects to the lat content attribute. No effect on map dynamic state.
lonGet or set the map's longitude. Reflects to the lon content attribute. No effect on map dynamic state.
projectionThe map's projection. Reflects the projection attribute.
zoomGet or set the map's zoom level. Reflects to the zoom content attribute. No effect on map dynamic state.

controls

To add controls to the map:

let map = document.querySelector('mapml-viewer');
map.controls = true; // or false to remove controls

To check whether the map has controls toggled on or off:

let map = document.querySelector('mapml-viewer');
let controlsAdded = map.controls;

controlsList

The controlsList property returns a DOMTokenList that helps the user select what controls to display on the mapml-viewer element based on the possible values.

To set the controlslist attribute:

let map = document.querySelector('mapml-viewer');
map.controlsList.value = "noreload nozoom"; // values can be noreload | nofullscreen | nozoom | nolayer
map.controlsList.add("nofullscreen"); // can also add using the 'add' method
map.controlsList.toggle("nolayer"); // can also toggle using the 'toggle' method
// view all methods here - https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList

To get the value of the controlslist:

let map = document.querySelector('mapml-viewer');
let controlsList = map.controlsList.value;

extent

Read-only. To get the map's extent:

let map = document.querySelector('mapml-viewer');
let extent = map.extent;
View Sample Extent
/**
*extent =
* {
* {
* "topLeft": {
* "tcrs": [
* {
* "horizontal": 906.7586206896551,
* "vertical": 981.7241379310345
* },
* ...
* ],
* "tilematrix": [
* {
* "horizontal": 3.5420258620689653,
* "vertical": 3.8348599137931036
* },
* ...
* ],
* "gcrs": {
* "horizontal": -93.05456518322721,
* "vertical": 63.783997873304855
* },
* "pcrs": {
* "horizontal": 131686.24163915217,
* "vertical": 1646487.1729743406
* }
* },
* "bottomRight": {
* "tcrs": [
* {
* "horizontal": 914.9655172413793,
* "vertical": 1015.5172413793102
* },
* ...
* ],
* "tilematrix": [
* {
* "horizontal": 3.574084051724138,
* "vertical": 3.9668642241379306
* },
* ...
* ],
* "gcrs": {
* "horizontal": -85.62509797700041,
* "vertical": 52.14641630380798
* },
* "pcrs": {
* "horizontal": 446541.0380154103,
* "vertical": 350026.2467191592
* }
* },
* "projection": "CBMTILE",
* "zoom": {
* "minZoom": 0,
* "maxZoom": 25
* }
* }
* }
*/

lat

To set the latitude:

let map = document.querySelector('mapml-viewer');
map.lat = 21.4; // if it's an invalid value, nothing happens

Note that the value supplied does not affect the map viewer state, except at document load, or when an instance of a <mapml-viewer> element is constructed and programmatically added to the DOM. To change the value, use zoomTo();

To get the latitude:

let map = document.querySelector('mapml-viewer');
let latitude = map.lat;

lon

To set the longitude:

let map = document.querySelector('mapml-viewer');
map.lon = 21.4; // if it's an invalid value, nothing happens

Note that the value supplied does not affect the map viewer state, except at document load, or when an instance of a <mapml-viewer> element is constructed and programmatically added to the DOM. To change the value, use zoomTo();

To get the longitude:

let map = document.querySelector('mapml-viewer');
let longitude = map.lon;

projection

To set/update the projection:

let map = document.querySelector('mapml-viewer');
map.projection = "CBMTILE"; // if it's an invalid/undefined projection, nothing happens

To get the projection:

let map = document.querySelector('mapml-viewer');
let projection = map.projection;

zoom

To set the zoom:

let map = document.querySelector('mapml-viewer');
map.zoom = 3; // if it's an invalid value, will default to 0

Note that the value supplied does not affect the map viewer state, except at document load, or when an instance of a <mapml-viewer> element is constructed and programmatically added to the DOM. To change the value, use zoomTo();

To get the longitude:

let map = document.querySelector('mapml-viewer');
let zoom = map.zoom;

Methods

MethodDescription
back()Navigates back one state in the map's movement history.
forward()Navigates forward in the map's panning history.
reload()Clear the map's panning history and return to the starting location.
toggleDebug()Toggle the debug functionality of the map.
viewSource()View the source of the map.
defineCustomProjection(options)Define a custom projection for use by the page.
zoomTo(lat, lon, zoom)Fly or pan the map to a (new) location and zoom level.
geojson2mapml(json, options)Add a GeoJSON Layer to the map.
matchMedia(mediaQueryString)Returns a MediaQueryList-like object.

back()

To go back in the map's history:

let map = document.querySelector('mapml-viewer');
map.back();

forward()

To go forward in the map's history:

let map = document.querySelector('mapml-viewer');
map.forward();

reload()

To clear the map's history and return to the initial location:

let map = document.querySelector('mapml-viewer');
map.reload();

toggleDebug()

To toggle the map's debug mode:

let map = document.querySelector('mapml-viewer');
map.toggleDebug();

viewSource()

To view the map's view source:

let map = document.querySelector('mapml-viewer');
map.viewSource();

defineCustomProjection(options)

MapML defines a few built-in tiled CRS projections, including Web Mercator (OSMTILE), pseudo-plate carrée (WGS84), and Canada's base map tile grid (CBMTILE).

The <mapml-viewer> custom element provides the custom projections API, which gives you the ability to create custom projections and use them in the <mapml-viewer> element, defined using extended JSON-based "proj4" syntax, supported by the proj4js library.

We won't discuss the actual <mapml-viewer> element here, except to say that the map projection attribute should have the exact same value of the projection member of the JSON object you pass to the custom projections API's defineCustomProjection method, and every <map-layer> element in the map must declare and be encoded in that coordinate system, in order to display correctly.

The custom projections API is provided by the <mapml-viewer> element. In a browser implementation, the API might be defined on the window object, but because of the ES6 modules used by custom elements, it is convenient to locate it on the mapping element which uses it.

To successfully call the defineCustomProjection method, you need to encode the projection method and parameters as members of a JSON string. The process of doing this is not always simple, but is helped by resources such as https://spatialreference.org, where you can obtain the proj4 version of virtually any CRS definition.

Remember to enclose member names in quotes followed by a colon: e.g. "projection": "MY_PROJECTION_NAME". String values are also enclosed in quotes, and numbers and arrays following normal JSON syntax.

There are several required members to a custom projection definition:

  • projection - this is a string name you give to your projection. We recommend using UPPERCASE to make projection names stand out. Colon ":" characters in the name are not permitted, because these names should not be confused with EPSG: or ogc: URI code lists, because what is being defined here is a CRS that has Web mapping specific parameters, discussed below.
  • proj4string - This string is processed by proj4js, so needs to provide parameters of a projection method supported by that library, in the format that it supports.
  • origin - an array of two numbers representing the origin of the tile grid in coordinates of the projected coordinate system, typically meters. The origin is always at the upper left of the tile grid space, and the column and row numbers increase to the right and down, respectively, following the WMTS standard. If your tile source is configured according to the "TMS" community standard, you
  • resolutions - an array of numbers, sorted in descending order of size in meters, of the "real-world" dimensions of a square pixel. The resolution is calculated using a nominal pixel size of 0.28mm, defined by the WMTS standard. NOTE THIS IS NOT TYPICALLY THE SAME VALUE THAT IS USED BY ESRI TILE SERVICES, WHICH USE 96 DPI AS THE NOMINAL SIZE (settable). Because scale varies over the extent of any projected coordinate system, the pixel resolution is usually valid only in limited locations, for example in Web Mercator, along the equator. The locations where pixel resolution is valid depend on the projection method and parameters. The set of resolutions must match the set of resolutions of tiles in a cache, if you intend to use your custom projection with an existing tile service.
  • bounds - an array of two arrays of coordinate pairs, defining a bounding box around part of the projected coordinate system, in meters typically. Requests should be valid and latitude / longitude are defined within these bounds. Requests for maps, tiles and coordinate transformations that fall completely outside these bounds will not execute, preventing redundant traffic and errors.
  • tilesize - tiles are always square, and usually 256 pixels on a side. You can specify another size here as an integer value. Values of 256, 512, 1024, 2048 or 4096 should work.

zoomTo(lat, lon, zoom)

To change the map's center location and zoom level:

var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};

function success(pos) {
var crd = pos.coords;

let map = document.querySelector('mapml-viewer');
map.zoomTo(crd.latitude,crd.longitude, 17); // hard-coded zoom
// could calculate a zoom based on accuracy of position
console.log(`More or less ${crd.accuracy} meters.`);
}

function error(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
}

navigator.geolocation.getCurrentPosition(success, error, options);

geojson2mapml(json, options)

Convert a GeoJSON feature or feature collection string or object to MapML <map-layer> containing one or more <map-feature> elements. Returns and adds the converted layer element to the map.

tip

Check out this application using the geojson2mapml API!

Parameters

ParameterDescription
<String | Object> jsonA GeoJSON string or object.
<Object> optionsOptional. A set of key/value pairs that customize the output MapML layer. All options are optional and described below.

Options

<Object> A set of key/value pairs that customize the output MapML layer. All options are optional and detailed below.

OptionTypeDefaultDescription
label<String>json.name, json.title or "Layer"Sets the output layer's label.
projection<String>map.projection or OSMTILESets the output layer's projection. Defined values include: OSMTILE, CBMTILE, WGS84, and APSTILE.
caption<String | Function>json.features[i].id or the label valueA function that accepts the feature JSON and returns a string, OR a string that is the name of a property to be mapped to the featurecaption. If a matching property is not found, the string provided will be used as the feature caption value. See basic options usage for an example.
properties<Function | String | HTMLElement>Properties will be mapped to an HTML table.Specifies how the properties are mapped. <Function> - A function that accepts one argument - the GeoJSON feature object - and which must return an HTMLElement that becomes the single child element of the <map-properties> element. <String> - A string that will be parsed and used as the single child element of the <map-properties> element for all features. <HTMLElement> - an element that will be used as the single child element of <map-properties> element for all features. See basic options usage for an example.
geometryFunction<Function>MapML geometry will mirror the GeoJSON geometry value<Function> A function to modify the generated descendants of <map-geometry> which can add classes, hyperlinks and span's to the instance. Plain <map-geometry> element will be created by default. The function accepts two arguments: The generated child element of <map-geometry> and the feature json object to return a modified child element of the <map-geometry> element. See basic options usage for an example.

matchMedia(mediaQueryString)

While not strictly 'media' features, some dynamic map properties can be combined in queries with standard media features, for example the 'prefers-color-scheme' feature, to enable a map container / media-query-like interface.

matchMedia(mediaQueryString) returns a MediaQueryList-like object. The matches boolean-valued property of the object can be used for an immediate determination of whether the map meets the queried feature conditions. To react to changes in the map state / media conditions, use MediaQueryList.addEventListener('change', callbackFn) to add an event listener for change events that are triggered by changes in the state of the queried map properties (projection, zoom, extent); any change to the map that results in a change in state of the MediaQueryListEvent matches boolean propertytriggers the change event and calls the callbackFn.

Supported map 'media' query features

Feature nameDescription
map-zoomRange of integers Used to evaluate if map-zoom is of a certain value or within a range
map-projectionDiscrete string values - known values include OSMTILE, CBMTILE, WGS84, APSTILE. Can be extended with custom projections.
map-top-left-eastingRange of integers - Decimal values are not supported.
map-top-left-northingRange of integers - Decimal values are not supported.
map-bottom-right-eastingRange of integers - Decimal values are not supported.
map-bottom-right-northingRange of integers - Decimal values are not supported.
prefers-map-contentDiscrete string values - supported values include: image, tile, feature, table. Preferences can be established via multi-select in the MapML browser extension
prefers-color-schemeDiscrete string values - supported values are light and dark
prefers-lang2-character language code returned by navigator.language, based on user's browser display language setting

Events

Event nameDescription
layerchangeFired when a layer changes src, usually by the user following a link.
loadFired when all layers have finished loading content
clickFired when the map receives both mousedown and mouseup events
dblclickFired when the user double clicks or taps the map
mousemoveFired repeatedly as the mouse cursor traverses the map
mouseoverFired once as the mouse cursor enters the map
mouseoutFired once as the mouse cursor exits the map
mousedownFired when the mouse's primary key is pressed down with cursor over the map
mouseupFired when the mouse's primary key is released with cursor over the map
movestartFired before the map starts to move / viewport changes
moveFired repeatedly as the map moves.
moveendFired after the map stops moving
zoomstartFired before the map changes zoom level
zoomFired repeatedly as the map changes zoom
zoomendFired after the map has changed zoom level
preclickFired before a click on the map is triggered. May not be a primitive.
contextmenuFired when user right-clicks or long presses on map. May not be a primitive.

Examples

geojson2mapml

Basic options usage

Showcasing how use each option.

geojson2mapml label option
geojson2mapml(json, {label: "Downtown Ottawa"});

Options string

An example showcasing how strings can be used to set label, projection, caption and properties options.

let map = document.querySelector('mapml-viewer');
let json = {
"name": "Default Name",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-75.6916809,45.4186964]
},
"properties": {"desc": "This is a Point"}
};

// GeoJSON To MapML
let output = map.geojson2mapml(json, {label: "Example 1", projection: "CBMTILE", caption: "desc", properties: "<h3>This is a property heading</h3>"});
Click to view the output HTMLElement
<map-layer label="Example 1" checked="">
<map-meta name="projection" content="CBMTILE"></map-meta>
<map-meta name="cs" content="gcrs"></map-meta>
<map-feature>
<map-featurecaption>This is a Point</map-featurecaption>
<map-geometry>
<map-point>
<map-coordinates>-75.6916809 45.4186964</map-coordinates>
</map-point>
</map-geometry>
<map-properties>
<h3>This is a property heading</h3>
</map-properties>
</map-feature>
</map-layer>

Options function

An example showcasing how functions can be used to set caption and properties options.

let map = document.querySelector('mapml-viewer');
let json = {
"name": "Default Name",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-75.6916809,45.4186964]
},
"properties": {"desc": "This is a Point"}
};

// function to set caption
let cap = function c(j) {
let str = "This point is located at: (" + j.geometry.coordinates[0] + ", " + j.geometry.coordinates[1] + ").";
return str;
}

// function to set properties
let prop = function f(p) {
let parser = new DOMParser();
return parser.parseFromString("<h1>" + p.properties.desc + "'s property</h1>", "text/html").body.firstChild;
}

// GeoJSON To MapML
let output = map.geojson2mapml(json, {label: "Example 2", caption: cap, properties: prop});
Click to view the output HTMLElement
<map-layer label="Example 2" checked="">
<map-meta name="projection" content="OSMTILE"></map-meta>
<map-meta name="cs" content="gcrs"></map-meta>
<map-feature>
<map-featurecaption>This point is located at: (-75.6916809, 45.4186964).</map-featurecaption>
<map-geometry>
<map-point>
<map-coordinates>-75.6916809 45.4186964</map-coordinates>
</map-point>
</map-geometry>
<map-properties>
<h1>This is a Point's property</h1>
</map-properties>
</map-feature>
</map-layer>

Default options

An example showcasing default output when no options are provided.

let map = document.querySelector('mapml-viewer');
let json = {
"title": "Point Geometry",
"bbox": [-75.916809, 45.886964, -75.516809, 45.26964],
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-75.6916809, 45.4186964]
},
"properties": {
"prop0": "This is a Point"
}
}]
};

// GeoJSON To MapML
let output = map.geojson2mapml(json);
Click to view the output HTMLElement
<map-layer label="Point Geometry" checked="">
<map-meta name="extent" content="top-left-longitude=-75.916809, top-left-latitude=45.886964, bottom-right-longitude=-75.516809,bottom-right-latitude=45.26964"></map-meta>
<map-meta name="projection" content="OSMTILE"></map-meta>
<map-meta name="cs" content="gcrs"></map-meta>
<map-feature>
<map-featurecaption>Point Geometry</map-featurecaption>
<map-geometry>
<map-point>
<map-coordinates>-75.6916809 45.4186964</map-coordinates>
</map-point>
</map-geometry>
<map-properties>
<table>
<thead>
<tr>
<th role="columnheader" scope="col">Property name</th>
<th role="columnheader" scope="col">Property value</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">prop0</th>
<td itemprop="prop0">This is a Point</td>
</tr>
</tbody>
</table>
</map-properties>
</map-feature>
</map-layer>

defineCustomProjection

Basic options usage

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Example Custom Projection</title>
<script type="module" src="./mapml.js"></script>
<script type="module">
let customProjectionDefinition = `{
"projection": "ATLAS_POLAR_MAP",
"proj4string" : "+proj=aeqd +lat_0=90 +lon_0=-90 +x_0=0 +y_0=0 +ellps=sphere +units=m +no_defs +type=crs",
"origin" : [-20015200,20015200],
"resolutions" : [33073,16536.5,8268.246,4134.123,2067.061,1033.531,516.765],
"bounds" : [[4979939,-4846977],[-5139071,3980038]],
"tilesize" : 256
}`;
let map = document.querySelector("mapml-viewer");
let cProjection = map.defineCustomProjection(customProjectionDefinition);
map.projection = cProjection;
</script>
</head>
<body>
<mapml-viewer projection="ATLAS_POLAR_MAP" zoom="2" lat="83.48919" lon="-87.7687" controls>
<map-layer label="Atlas of Canada Polar Wall Map" checked>
<map-link rel="license" title="Canadian Federal Geospatial Platform" href="https://geoappext.nrcan.gc.ca/arcgis/rest/services/FGP/NCR_RCN/MapServer/"></map-link>
<map-extent units="ATLAS_POLAR_MAP" checked hidden>
<map-input type="zoom" name="z" min="0" max="6" value="6" ></map-input>
<map-input type="location" name="x" axis="column" units="tilematrix" min="116" max="186"></map-input>
<map-input type="location" name="y" axis="row" units="tilematrix" min="125" max="184"></map-input>
<map-link rel="tile" tref="https://geoappext.nrcan.gc.ca/arcgis/rest/services/FGP/NCR_RCN/MapServer/tile/{z}/{y}/{x}/"></map-link>
<map-link rel="tile" tref="https://geoappext.nrcan.gc.ca/arcgis/rest/services/FGP/NCR_RCN_A/MapServer/tile/{z}/{y}/{x}/"></map-link>
</map-extent>
</map-layer>
</mapml-viewer>
</body>
</html>

matchMedia

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example map media query</title>
// adjust the path to where you can find the distributed mapml.js artifact
<script type="module" src="./mapml.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const map = document.querySelector('mapml-viewer');
map.whenReady().then(() => {
const extent = map.extent;

const topLeftEasting = Math.trunc(extent.topLeft.pcrs.horizontal);
const topLeftNorthing = Math.trunc(extent.topLeft.pcrs.vertical);
const bottomRightEasting = Math.trunc(extent.bottomRight.pcrs.horizontal);
const bottomRightNorthing = Math.trunc(extent.bottomRight.pcrs.vertical);

// Format the media query string to detect overlap:
// (xminm < xmaxq) and (xmaxm > xminq) and (yminm < ymaxq) and (ymaxm > yminq)
const query = `(map-projection: OSMTILE) and (7 < map-zoom < 14) and (map-top-left-easting < ${bottomRightEasting}) and (map-bottom-right-easting > ${topLeftEasting}) and (map-bottom-right-northing < ${topLeftNorthing}) and (map-top-left-northing > ${bottomRightNorthing})`;

const matcher = map.matchMedia(query);

// create a layer to visually represent the query as the map moves
const f = `<map-layer checked label="test media query"><map-meta name="projection" content="OSMTILE"></map-meta>
<map-meta name="cs" content="pcrs"></map-meta><map-feature><map-properties>${query}</map-properties>
<map-geometry><map-polygon><map-coordinates>${topLeftEasting} ${topLeftNorthing}
${bottomRightEasting} ${topLeftNorthing} ${bottomRightEasting} ${bottomRightNorthing} ${topLeftEasting} ${bottomRightNorthing}
${topLeftEasting} ${topLeftNorthing}</map-coordinates</map-polygon></map-geometry></map-feature></map-layer>`;

const parser = new DOMParser();
const layer = parser
.parseFromString(f, 'text/html')
.querySelector('map-layer');
map.appendChild(layer);
const changeDisplayLayer = () => {
if (matcher.matches) {
layer.checked = true;
layer.hidden = false;
alert('Feature overlaps the map');
} else {
layer.checked = false;
layer.hidden = true;
alert('Feature does not overlap the map');
}
};
changeDisplayLayer();
matcher.addEventListener('change', changeDisplayLayer);
});
});
</script>
</head>
<body>
<mapml-viewer projection="OSMTILE" zoom="14" lat="45.406314" lon="-75.6883335" controls>
<map-layer label="OpenStreetMap" checked>
<map-link rel="license" title="© OpenStreetMap contributors CC BY-SA"
href="https://www.openstreetmap.org/copyright"></map-link>
<map-extent units="OSMTILE" checked hidden>
<map-input name="z" type="zoom" value="18" min="0" max="18"></map-input>
<map-input name="x" type="location" units="tilematrix" axis="column" min="0" max="262144"></map-input>
<map-input name="y" type="location" units="tilematrix" axis="row" min="0" max="262144"></map-input>
<map-link rel="tile" tref="https://tile.openstreetmap.org/{z}/{x}/{y}.png"></map-link>
</map-extent>
</map-layer>
</mapml-viewer>
</body>
</html>

Specifications

Specification
HTMLMapmlViewerElement

Requirements

Report problems with these requirements on GitHub

requirement enhancement impractical undecided under discussion

SpecViewerAPI
Propertiesfullfullfull
Methodspartial *fullpartial *
Exceptions *
  1. No specification will be provided for toggleDebug() or viewSource() methods.
  2. The defineCustomProjection method is implemented, but not yet specified
  3. The custom projections API (defineCustomProjection) is under discussion, in particular, the options parameter's format.
  4. The geojson2mapml method's options parameter specification is not final.