---
title: Viewer
description: The Viewer can be used to display Basemaps with a single Marker, or many Overlays (Markers, Lines and Shapes).
---

# Viewer

The Viewer can be used to display [Basemaps](map#basemaps) with a single Marker, or many Overlays (Markers, Lines and Shapes). Each Overlay can be given a Title, Description and Image URL, which are displayed in a Popup when the Overlay is clicked. For security, the Title is rendered as plain text, the Description is sanitised HTML (safe tags such as `p`, `a`, `br`, `strong`, `em`, `ul`/`ol`/`li`, `div`, `span` and `blockquote` are allowed; scripts and event handlers are stripped), and Image URLs must use `http`/`https`.

Features include:

- **Image Gallery** &ndash; Thumbnails for Markers currently in view on the Map are displayed and can be clicked open the Marker popup.
- **Overlay Filter** &ndash; Pick which Overlays are currently visible by [Type](map#types).
- **Marker Clustering** &ndash; Markers that are close together are stacked, to declutter the Map.
- **Elevation Profile** &ndash; An interactive elevation profile for Lines that have elevation data.

## Creation

To create a Viewer Instance, use the `viewer` method of the `Waymark_Map_Factory`:

```javascript
// Create a Viewer Instance
const viewer = window.Waymark_Map_Factory.viewer();
```

Options are passed to the Instance `init` method to configure the Viewer.

## Options

These options, provided in the `viewer_options` object, are used to customise the Viewer Mode.

| Option                | Values              | Description                                                                                                                                                                                                                                       | Example             |
| --------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `show_gallery`        | `1`/`0`             | Whether to display an image gallery for Markers that have images. Thumbnails for Markers currently in view on the Map are displayed and clicking on a thumbnail will centre the Map on the Marker and open the popup.                             | `1`                 |
| `show_filter`         | `1`/`0`             | Allow the user to filter which Overlays are currently visible on Map.                                                                                                                                                                             | `1`                 |
| `show_cluster`        | `1`/`0`             | Whether to cluster (stack) Markers that are close together, to declutter the Map.                                                                                                                                                                 | `1`                 |
| `cluster_radius`      | number              | The maximum radius that a cluster will cover from the central Marker (in pixels). Decreasing will make more, smaller clusters. Default `80`.                                                                                                      | `80`                |
| `cluster_threshold`   | `0`-`18`            | Markers will not be clustered above this zoom level.                                                                                                                                                                                              | `14`                |
| `show_elevation`      | `1`/`0`             | Whether to display an interactive elevation profile graph below the Map for Lines that have elevation data.                                                                                                                                       | `1`                 |
| `elevation_div_id`    | string              | The ID of the HTML element to contain the elevation profile graph. The default is `waymark-elevation` and if this element does not exist, it will be created **inside** the Map Container.                                                        | `waymark-elevation` |
| `elevation_units`     | `metric`/`imperial` | Display elevation data in metric (m/km) or imperial (ft/mi) units.                                                                                                                                                                                | `metric`            |
| `elevation_colour`    | CSS Colour          | The colour of the elevation graph and associated Line, provided as a CSS colour (e.g. `white`, `#ffba00`, `rgb(255, 186, 0)`).                                                                                                                    | `#b42714`           |
| `elevation_initial`   | `1`/`0`             | Whether to show the elevation profile initially when the Map loads, or wait for a Line to be clicked.                                                                                                                                             | `0`                 |
| `sleep_delay_seconds` | number              | How many seconds before scroll zoom is enabled. `0` seconds will mean no delay (disabling this feature). A large number of seconds like `3600` (an hour) will essentially _disable hover to wake_, meaning the user will need to _click_ to wake. | `3600`              |
| `sleep_do_message`    | `1`/`0`             | Whether to display a message while scroll zoom is disabled.                                                                                                                                                                                       | `1`                 |
| `sleep_wake_message`  | string              | The message to display while scroll zoom is disabled.                                                                                                                                                                                             | `Click to Wake`     |

### Example Config

This configuration enables all available Viewer features:

```javascript
const config = {
  viewer_options: {
    show_gallery: true,
    show_filter: true,
    show_cluster: true,
    show_elevation: true,
  },
};
```

## Initialisation

Once the configuration is set, the `init` method is called to initialise the Map:

```javascript
// Initialise with our options
viewer.init(config);
```

The Map is now displayed on the page according to the provided options.

## Loading Data

Waymark JS supports loading data from [GeoJSON](https://geojson.org/), [GPX](https://www.topografix.com/gpx.asp) and [KML](https://developers.google.com/kml) files.

### GeoJSON

After the Map is initialised, data can be loaded using the `load_json` method, which accepts a [GeoJSON](https://geojson.org/) object as an argument.

```javascript
viewer.load_json({
  type: "FeatureCollection",
  features: [
    {
      geometry: { type: "Point", coordinates: [-85.038, 49.4595] },
      type: "Feature",
      properties: { type: "food" },
    },
  ],
});
```

To load a GeoJSON file using [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), the `load_json` method is called within the `fetch` promise to ensure the data is available:

```javascript
// Load GeoJSON
fetch("../examples/assets/geo/route.geojson")
  .then((response) => response.json())
  .then((geojson) => {
    viewer.load_json(geojson);
  });
```

### GPX and KML

To load data from a GPX or KML file, the file is fetched and parsed as XML, then converted to GeoJSON using the included `toGeoJSON` library using the `gpx` or `kml` methods. The resulting GeoJSON is then added to the Map.

See this example in action [here](examples/viewer/formats.html).

```javascript
// Load GPX
fetch("../examples/assets/geo/route.gpx")
  .then((response) => response.text())
  // As Text
  .then((gpx) => {
    // Parse GPX
    const parsed = new DOMParser().parseFromString(gpx, "text/xml");

    // Convert to GeoJSON
    const geojson = toGeoJSON.gpx(parsed) || {};

    // Ensure is valid FeatureCollection
    if (geojson.type !== "FeatureCollection") {
      return;
    }

    // Add to Map
    viewer.load_json(geojson);
  });

// Load KML
fetch("../assets/geo/route.kml")
  .then((response) => response.text())
  // As Text
  .then((kml) => {
    // Parse KML
    const parsed = new DOMParser().parseFromString(kml, "text/xml");

    // Convert to GeoJSON
    const geojson = toGeoJSON.kml(parsed) || {};

    // Ensure is valid FeatureCollection
    if (geojson.type !== "FeatureCollection") {
      return;
    }

    // Add to Map
    viewer.load_json(geojson);
  });
```

> [!NOTE]
> The object is expected to be a [FeatureCollection](https://geojson.org/geojson-spec.html#feature-collection-objects) with an array of [Features](https://geojson.org/geojson-spec.html#feature-objects), even if only one Feature is being added.

## Examples

### Marker With Custom Icon

Here we are creating a new Viewer Instance, setting some [options](map#map-options), and adding a Marker to the Map.

```html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />

    <!-- Stylesheet -->
    <link
      rel="stylesheet"
      href="https://www.ogis.org/waymark-js/dist/latest/css/waymark-js.min.css"
    />

    <!-- JS -->
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="https://www.ogis.org/waymark-js/dist/latest/js/waymark-js.min.js"></script>
  </head>
  <body>
    <div id="waymark-map"></div>

    <script>
      // Create viewer Instance
      const viewer = window.Waymark_Map_Factory.viewer();

      // Initialise with our options
      viewer.init({
        map_options: {
          // Initial Map Zoom
          map_init_zoom: 14,

          // Our Pub Icon
          marker_types: [
            {
              marker_title: "Pub",
              marker_icon: "ion-beer",
              marker_colour: "brown",
            },
          ],
        },
      });

      // Load GeoJSON
      viewer.load_json({
        type: "FeatureCollection",
        features: [
          {
            type: "Feature",
            properties: {
              type: "pub",
              title: "The Scarlet Ibis",
              description:
                "Great pub, great food! Especially after a Long Ride 🚴🍔🍟🍺🍺💤",
              image_large_url:
                "https://www.ogis.org/waymark-js/assets/img/pub.jpeg",
            },
            geometry: {
              type: "Point",
              coordinates: [-128.0094, 50.6539],
            },
          },
        ],
      });
    </script>
  </body>
</html>
```

### Multiple Overlays From File

Here we are creating a new Viewer Instance initialised with some [Types](map#types) and loading GeoJSON data from a file.

```html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />

    <!-- Stylesheet -->
    <link
      rel="stylesheet"
      href="https://www.ogis.org/waymark-js/dist/latest/css/waymark-js.min.css"
    />

    <!-- JS -->
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="https://www.ogis.org/waymark-js/dist/latest/js/waymark-js.min.js"></script>
  </head>
  <body>
    <div id="waymark-map"></div>

    <script>
      // Create Viewer Instance
      const viewer = window.Waymark_Map_Factory.viewer();

      // Initialise with our options
      viewer.init({
        // Viewer Specific Options
        viewer_options: {
          show_gallery: "1",
          show_filter: "1",
          show_cluster: "1",
          show_elevation: "1",
          elevation_units: "imperial",
          elevation_colour: "#70af00",
          elevation_initial: "1",
          sleep_do_message: "1",
        },

        // General Map Options
        map_options: {
          debug_mode: true,

          // Line Types
          line_types: [
            {
              line_title: "Route",
              line_colour: "green",
            },
          ],

          // Marker Types
          marker_types: [
            {
              marker_title: "Photo",
              icon_type: "icon",
              marker_icon: "ion-camera",
              marker_colour: "#70af00",
              icon_colour: "#ffffff",
            },
            {
              marker_title: "Information",
              icon_type: "icon",
              marker_icon: "ion-information-circled",
              marker_colour: "#fbfbfb",
              icon_colour: "#0069a5",
            },
            {
              marker_title: "Alert",
              icon_type: "icon",
              marker_icon: "ion-android-alert",
              marker_colour: "#da3d20",
              icon_colour: "white",
            },
            {
              marker_title: "Food",
              icon_type: "icon",
              marker_icon: "ion-pizza",
              marker_colour: "#da3d20",
              icon_colour: "#ffba00",
            },
            {
              marker_title: "Beer",
              icon_type: "icon",
              marker_icon: "ion-beer",
              marker_colour: "#fbfbfb",
              icon_colour: "#754423",
            },
            {
              marker_title: "Camp",
              icon_type: "icon",
              marker_icon: "ion-android-home",
              marker_colour: "#a43233",
              icon_colour: "#ffffff",
            },
          ],
        },
      });

      // Load GeoJSON asynchronously from file
      const geojson = fetch("./assets/geo/route.geojson")
        .then((response) => response.json())
        .then((data) => {
          viewer.load_json(data);
        });
    </script>
  </body>
</html>
```
