NIKA OnlyMapJS Latest release
Discord GitHub Docs

← OnlyMapJS Gallery / Rasters & tiles

Add a national grid WMTS

Draw a WMTS published on a national grid: swisstopo's map and aerial imagery in Swiss LV95, placed on a Web Mercator map.

Open full screen ↗ View source ↗
<!DOCTYPE html>
<!--
  Many national mapping agencies publish their tiles on their OWN grid, not
  Web Mercator's: swisstopo on LV95 (EPSG:2056), PDOK on RD New (28992),
  Finland's MML on TM35FIN (3067), Germany's AdV on UTM (25832). Such a WMTS
  is a raster TileLayer with two things the service states in its
  GetCapabilities:

    - its tile address, with {TileMatrix}, {TileRow} and {TileCol} (and
      {Time}, filled from the layer's `time`), and
    - its tile matrix set, as tile-matrix-set: the grid's CRS, its top-left
      origin, the resolution of each level and the tile size.

  The layer picks the level nearest the view's ground resolution, asks for
  the grid tiles that cover the view, and warps each onto the map — so the
  national map lines up with everything else on it, Web Mercator or not.

  tile-matrix-set takes three spellings: this short one; the TileMatrixSet as
  WMTS capabilities state it (QGIS hands that over as JSON); or an OGC tile
  matrix set. `extent` keeps requests inside the published grid.

  The map: swisstopo's national map and its aerial imagery, both on the
  Swiss grid. Switch between them in the legend and zoom into a valley: the
  levels go down to half a metre of map, and a quarter of a metre of photo.
-->
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OnlyMapJS — Add a national grid WMTS</title>
  <link rel="stylesheet" href="https://unpkg.com/@nika-js/onlymap/dist/onlymapjs.css" />
  <script type="module" src="https://unpkg.com/@nika-js/onlymap/dist/onlymap.standalone.js"></script>
  <style>
    :root { color-scheme: light; }
    html, body { margin: 0; height: 100%; font-family: system-ui, sans-serif; }
    om-map { display: block; height: 100vh; }
  </style>
</head>
<body>

  <om-map center="[8.23, 46.82]" zoom="7.4" basemap="positron">

    <!-- swisstopo's national map (Landeskarte) in colour. {Time} is the
         WMTS time dimension; "current" is the latest edition. The grid is
         LV95's: origin at its top-left corner, 27 levels from 4 km to 0.5 m
         a pixel, 256-pixel tiles. -->
    <om-layer id="map" type="TileLayer" tile-size="256"
              data="https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/{Time}/2056/{TileMatrix}/{TileCol}/{TileRow}.jpeg"
              time="current"
              tile-matrix-set='{"crs": "EPSG:2056", "origin": [2420000, 1350000], "extent": [2420000, 1030000, 2900000, 1350000], "tileSize": 256,
                                "resolutions": [4000, 3750, 3500, 3250, 3000, 2750, 2500, 2250, 2000, 1750, 1500, 1250, 1000, 750, 650, 500, 250, 100, 50, 20, 10, 5, 2.5, 2, 1.5, 1, 0.5]}'
              label="National map (swisstopo, EPSG:2056)" color="#e11d48"></om-layer>

    <!-- SWISSIMAGE, the aerial mosaic: same grid, one level deeper (0.25 m). -->
    <om-layer id="photo" type="TileLayer" tile-size="256" visible="false"
              data="https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.swissimage/default/{Time}/2056/{TileMatrix}/{TileCol}/{TileRow}.jpeg"
              time="current"
              tile-matrix-set='{"crs": "EPSG:2056", "origin": [2420000, 1350000], "extent": [2420000, 1030000, 2900000, 1350000], "tileSize": 256,
                                "resolutions": [4000, 3750, 3500, 3250, 3000, 2750, 2500, 2250, 2000, 1750, 1500, 1250, 1000, 750, 650, 500, 250, 100, 50, 20, 10, 5, 2.5, 2, 1.5, 1, 0.5, 0.25]}'
              label="Aerial imagery (SWISSIMAGE)" color="#65a30d"></om-layer>

    <om-widget type="legend" title="swisstopo" position="top-right" interactive></om-widget>
    <om-widget type="zoom-controls" position="bottom-right"></om-widget>
    <om-widget type="scale-bar" position="bottom-right"></om-widget>
    <om-widget type="attribution" position="bottom-start" text="© swisstopo"></om-widget>

    <om-widget position="top-left">
      <style>
        .panel { background: rgba(255,255,255,.92); color: #1f2937; padding: 10px 14px;
                 border-radius: 8px; font-size: 13px; max-width: 270px; line-height: 1.45;
                 box-shadow: 0 2px 10px rgba(0,0,0,.15); }
        .panel b { color: #be123c; }
      </style>
      <div class="panel">
        <b>A national map on its own grid.</b> swisstopo tiles in Swiss
        coordinates, placed on a Web Mercator map. Zoom into a valley, or
        switch to the aerial imagery in the legend.
      </div>
    </om-widget>

    <om-fallback>
      <p style="font: 15px system-ui, sans-serif; padding: 24px; max-width: 42ch">
        <strong>This map needs JavaScript.</strong><br />
        Open this file in a web browser such as Chrome, Safari, or Firefox.
      </p>
    </om-fallback>

  </om-map>

</body>
</html>