API-Beispiel: Geotracking-Demo

Eine Simulation der Geotracking-Funktion aus der Perspektive eines Fußgängers.

Durch die Simulation der Wegstrecke ist der Code in diesem Fall etwas umfangreicher. Den schlankeren Code für diese Funktion unter Berücksichtigung der echten Standortdaten eines Anwenders finden Sie auf unserer Geotracking-Seite.


<body>
    <div id="map" class="map">
      <div id="simulation-buttons">
        <button id="start-simulate" class="button-secondary">Simulation starten</button>
        <button id="stop-simulate" class="button-secondary" style="display: none">Simulation beenden</button>
      </div>
    </div>
</body>

<script>
  // create a background layer
  const baseLayer = new ol.layer.Tile({
  	source: new ol.source.XYZ({
      attributions: ['© 2024 <a target="_blank" href="http://www.mapz.com">mapz.com </a>\
              - Map Data: <a target="_blank" href="http://openstreetmap.org">OpenStreetMap</a>\
              (<a href="http://opendatacommons.org/licenses/odbl/1.0/" target="_blank">ODbL</a>)'],
      tilePixelRatio: 2,
      url:'https://tiles.mapz.com/mapproxy/v1/demo-817ca352/tiles/1.0.0/mapz_multicolor_base_hq/EPSG3857/{z}/{x}/{-y}.jpeg'
    })
  });

  const map = new ol.Map({
    target: document.getElementById('map'),
    logo: false,
    layers: [
      baseLayer
    ],
    view: new ol.View({
      center: ol.proj.transform([5.868668798, 45.64444874417562], 'EPSG:4326', 'EPSG:3857'),
      zoom: 17
    })
  });

  // EnableHighAccuracy
  const geolocation = new ol.Geolocation({
    trackingOptions: {
      enableHighAccuracy: true
    }
  });

  // Create geotracker
  const geotracker = new ol.mapz.control.Geotracker({
    // define position symbol
    marker: {
      src: 'https://mapz.com./api/static/images/position.svg',
      style: 'height: 60px;',
    },
    // set style for recorded track
    trackStyle: new ol.style.Style({
      stroke: new ol.style.Stroke({
        width: 5,
        color: 'rgba(239, 130, 20, 0.5)'
      })
    }),
    //don't start tracking automatically
    autostart: false,
    // rotate view when updating position
    rotate: false,
    // enable high accuracy
    enableHighAccuracy: true
  });

  map.addControl(geotracker);

  /*
   * All of the following code is used for simulating device movement
   */

  // simulate device move
  let simulationData;
  fetch('https://mapz.com./api/static/data/geolocation-orientation.json')
    .then((response) => response.json())
    .then((data) => (simulationData = data.data));

  // convert degrees to radians
  function degToRad(deg) {
    return deg * Math.PI * 2 / 360;
  }

  const startSimulateBtn = document.getElementById('start-simulate');
  const stopSimulateBtn = document.getElementById('stop-simulate');
  const geotrackerBtn = document.querySelector('.mapz-control-geotracker-button');
  let cancelSimulation = false;

  startSimulateBtn.onclick = function () {
    if (!simulationData) {
      return;
    }
    cancelSimulation = false;
    startSimulateBtn.style.display = 'none';
    stopSimulateBtn.style.display = '';
    geotracker.getGeolocation().setTracking(false);
    const coordinates = simulationData;

    const first = coordinates.shift();
    simulatePositionChange(first);

    let prevDate = first.timestamp;
    function geolocate() {
      if (cancelSimulation) {
        return;
      }
      const position = coordinates.shift();
      if (!position) {
        return;
      }
      const newDate = position.timestamp;
      simulatePositionChange(position);
      window.setTimeout(function () {
        prevDate = newDate;
        geolocate();
      }, (newDate - prevDate) / 0.5);
    }
    geolocate();
    map.on('postcompose', function () {
      map.render();
    });
    map.render();
  };

  function stopSimulation() {
    startSimulateBtn.style.display = '';
    stopSimulateBtn.style.display = 'none';
    cancelSimulation = true;
  }

  stopSimulateBtn.onclick = function () {
    stopSimulation();
  };
  geotrackerBtn.onclick = function () {
    stopSimulation();
  };

  function simulatePositionChange(position) {
    const coords = position.coords;
    const geolocation = geotracker.getGeolocation();
    geolocation.set('accuracy', coords.accuracy);
    geolocation.set('heading', degToRad(coords.heading));
    const position_ = [coords.longitude, coords.latitude];
    const projectedPosition = ol.proj.transform(position_, 'EPSG:4326', 'EPSG:3857');
    geolocation.set('position', projectedPosition);
    geolocation.set('speed', coords.speed);
    geolocation.changed();
  }
</script>

<style>
  #map {
    position: relative;
  }
  #simulation-buttons {
    position: absolute;
    z-index: 1;
    bottom: 0.5em;
    left: 0.5em;
  }
  #simulation-buttons button {
    background-color: #ef8214;
    background-color: #ef8214;
    color: white;
    font-weight: 700;
    border-radius: 5px;
    border: 1px solid white;
    font-size: 13px;
    padding: 7px 10px;
  }
  .mapz-control-geotracker {
    display: none !important;
  }
  .map {
    height: 400px;
    font-family: "HelveticaNeue", "Helvetica";
  }

</style>

<html>
    <head>
        <link rel='stylesheet' href='https://mapz.com./api/static/css/ol/7.3.0/ol.css' />
        <script src='https://mapz.com./api/static/javascript/lib/7.3.0/ol.js' type='text/javascript'></script>
        
        
        <style>
          #map {
            position: relative;
          }
          #simulation-buttons {
            position: absolute;
            z-index: 1;
            bottom: 0.5em;
            left: 0.5em;
          }
          #simulation-buttons button {
            background-color: #ef8214;
            background-color: #ef8214;
            color: white;
            font-weight: 700;
            border-radius: 5px;
            border: 1px solid white;
            font-size: 13px;
            padding: 7px 10px;
          }
          .mapz-control-geotracker {
            display: none !important;
          }
          .map {
            height: 400px;
            font-family: "HelveticaNeue", "Helvetica";
          }

        </style>
    </head>
    <body>
        <div id="map" class="map">
          <div id="simulation-buttons">
            <button id="start-simulate" class="button-secondary">Simulation starten</button>
            <button id="stop-simulate" class="button-secondary" style="display: none">Simulation beenden</button>
          </div>
        </div>
        <script>
          // create a background layer
          const baseLayer = new ol.layer.Tile({
          	source: new ol.source.XYZ({
              attributions: ['© 2024 <a target="_blank" href="http://www.mapz.com">mapz.com </a>\
                      - Map Data: <a target="_blank" href="http://openstreetmap.org">OpenStreetMap</a>\
                      (<a href="http://opendatacommons.org/licenses/odbl/1.0/" target="_blank">ODbL</a>)'],
              tilePixelRatio: 2,
              url:'https://tiles.mapz.com/mapproxy/v1/demo-817ca352/tiles/1.0.0/mapz_multicolor_base_hq/EPSG3857/{z}/{x}/{-y}.jpeg'
            })
          });

          const map = new ol.Map({
            target: document.getElementById('map'),
            logo: false,
            layers: [
              baseLayer
            ],
            view: new ol.View({
              center: ol.proj.transform([5.868668798, 45.64444874417562], 'EPSG:4326', 'EPSG:3857'),
              zoom: 17
            })
          });

          // EnableHighAccuracy
          const geolocation = new ol.Geolocation({
            trackingOptions: {
              enableHighAccuracy: true
            }
          });

          // Create geotracker
          const geotracker = new ol.mapz.control.Geotracker({
            // define position symbol
            marker: {
              src: 'https://mapz.com./api/static/images/position.svg',
              style: 'height: 60px;',
            },
            // set style for recorded track
            trackStyle: new ol.style.Style({
              stroke: new ol.style.Stroke({
                width: 5,
                color: 'rgba(239, 130, 20, 0.5)'
              })
            }),
            //don't start tracking automatically
            autostart: false,
            // rotate view when updating position
            rotate: false,
            // enable high accuracy
            enableHighAccuracy: true
          });

          map.addControl(geotracker);

          /*
           * All of the following code is used for simulating device movement
           */

          // simulate device move
          let simulationData;
          fetch('https://mapz.com./api/static/data/geolocation-orientation.json')
            .then((response) => response.json())
            .then((data) => (simulationData = data.data));

          // convert degrees to radians
          function degToRad(deg) {
            return deg * Math.PI * 2 / 360;
          }

          const startSimulateBtn = document.getElementById('start-simulate');
          const stopSimulateBtn = document.getElementById('stop-simulate');
          const geotrackerBtn = document.querySelector('.mapz-control-geotracker-button');
          let cancelSimulation = false;

          startSimulateBtn.onclick = function () {
            if (!simulationData) {
              return;
            }
            cancelSimulation = false;
            startSimulateBtn.style.display = 'none';
            stopSimulateBtn.style.display = '';
            geotracker.getGeolocation().setTracking(false);
            const coordinates = simulationData;

            const first = coordinates.shift();
            simulatePositionChange(first);

            let prevDate = first.timestamp;
            function geolocate() {
              if (cancelSimulation) {
                return;
              }
              const position = coordinates.shift();
              if (!position) {
                return;
              }
              const newDate = position.timestamp;
              simulatePositionChange(position);
              window.setTimeout(function () {
                prevDate = newDate;
                geolocate();
              }, (newDate - prevDate) / 0.5);
            }
            geolocate();
            map.on('postcompose', function () {
              map.render();
            });
            map.render();
          };

          function stopSimulation() {
            startSimulateBtn.style.display = '';
            stopSimulateBtn.style.display = 'none';
            cancelSimulation = true;
          }

          stopSimulateBtn.onclick = function () {
            stopSimulation();
          };
          geotrackerBtn.onclick = function () {
            stopSimulation();
          };

          function simulatePositionChange(position) {
            const coords = position.coords;
            const geolocation = geotracker.getGeolocation();
            geolocation.set('accuracy', coords.accuracy);
            geolocation.set('heading', degToRad(coords.heading));
            const position_ = [coords.longitude, coords.latitude];
            const projectedPosition = ol.proj.transform(position_, 'EPSG:4326', 'EPSG:3857');
            geolocation.set('position', projectedPosition);
            geolocation.set('speed', coords.speed);
            geolocation.changed();
          }
        </script>
    </body>
</html>

<style>
  :root,
  :host {
    --ol-background-color: white;
    --ol-accent-background-color: #F5F5F5;
    --ol-subtle-background-color: rgba(128, 128, 128, 0.25);
    --ol-partial-background-color: rgba(255, 255, 255, 0.75);
    --ol-foreground-color: #333333;
    --ol-subtle-foreground-color: #666666;
    --ol-brand-color: #00AAFF;
  }

  .ol-box {
    box-sizing: border-box;
    border-radius: 2px;
    border: 1.5px solid var(--ol-background-color);
    background-color: var(--ol-partial-background-color);
  }

  .ol-mouse-position {
    top: 8px;
    right: 8px;
    position: absolute;
  }

  .ol-scale-line {
    background: var(--ol-partial-background-color);
    border-radius: 4px;
    bottom: 8px;
    left: 8px;
    padding: 2px;
    position: absolute;
  }

  .ol-scale-line-inner {
    border: 1px solid var(--ol-subtle-foreground-color);
    border-top: none;
    color: var(--ol-foreground-color);
    font-size: 10px;
    text-align: center;
    margin: 1px;
    will-change: contents, width;
    transition: all 0.25s;
  }

  .ol-scale-bar {
    position: absolute;
    bottom: 8px;
    left: 8px;
  }

  .ol-scale-bar-inner {
    display: flex;
  }

  .ol-scale-step-marker {
    width: 1px;
    height: 15px;
    background-color: var(--ol-foreground-color);
    float: right;
    z-index: 10;
  }

  .ol-scale-step-text {
    position: absolute;
    bottom: -5px;
    font-size: 10px;
    z-index: 11;
    color: var(--ol-foreground-color);
    text-shadow: -1.5px 0 var(--ol-partial-background-color), 0 1.5px var(--ol-partial-background-color), 1.5px 0 var(--ol-partial-background-color), 0 -1.5px var(--ol-partial-background-color);
  }

  .ol-scale-text {
    position: absolute;
    font-size: 12px;
    text-align: center;
    bottom: 25px;
    color: var(--ol-foreground-color);
    text-shadow: -1.5px 0 var(--ol-partial-background-color), 0 1.5px var(--ol-partial-background-color), 1.5px 0 var(--ol-partial-background-color), 0 -1.5px var(--ol-partial-background-color);
  }

  .ol-scale-singlebar {
    position: relative;
    height: 10px;
    z-index: 9;
    box-sizing: border-box;
    border: 1px solid var(--ol-foreground-color);
  }

  .ol-scale-singlebar-even {
    background-color: var(--ol-subtle-foreground-color);
  }

  .ol-scale-singlebar-odd {
    background-color: var(--ol-background-color);
  }

  .ol-unsupported {
    display: none;
  }

  .ol-viewport,
  .ol-unselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
  }

  .ol-viewport canvas {
    all: unset;
  }

  .ol-selectable {
    -webkit-touch-callout: default;
    -webkit-user-select: text;
    -moz-user-select: text;
    user-select: text;
  }

  .ol-grabbing {
    cursor: -webkit-grabbing;
    cursor: -moz-grabbing;
    cursor: grabbing;
  }

  .ol-grab {
    cursor: move;
    cursor: -webkit-grab;
    cursor: -moz-grab;
    cursor: grab;
  }

  .ol-control {
    position: absolute;
    background-color: var(--ol-subtle-background-color);
    border-radius: 4px;
  }

  .ol-zoom {
    top: .5em;
    left: .5em;
  }

  .ol-rotate {
    top: .5em;
    right: .5em;
    transition: opacity .25s linear, visibility 0s linear;
  }

  .ol-rotate.ol-hidden {
    opacity: 0;
    visibility: hidden;
    transition: opacity .25s linear, visibility 0s linear .25s;
  }

  .ol-zoom-extent {
    top: 4.643em;
    left: .5em;
  }

  .ol-full-screen {
    right: .5em;
    top: .5em;
  }

  .ol-control button {
    display: block;
    margin: 1px;
    padding: 0;
    color: var(--ol-subtle-foreground-color);
    font-weight: bold;
    text-decoration: none;
    font-size: inherit;
    text-align: center;
    height: 1.375em;
    width: 1.375em;
    line-height: .4em;
    background-color: var(--ol-background-color);
    border: none;
    border-radius: 2px;
  }

  .ol-control button::-moz-focus-inner {
    border: none;
    padding: 0;
  }

  .ol-zoom-extent button {
    line-height: 1.4em;
  }

  .ol-compass {
    display: block;
    font-weight: normal;
    will-change: transform;
  }

  .ol-touch .ol-control button {
    font-size: 1.5em;
  }

  .ol-touch .ol-zoom-extent {
    top: 5.5em;
  }

  .ol-control button:hover,
  .ol-control button:focus {
    text-decoration: none;
    outline: 1px solid var(--ol-subtle-foreground-color);
    color: var(--ol-foreground-color);
  }

  .ol-zoom .ol-zoom-in {
    border-radius: 2px 2px 0 0;
  }

  .ol-zoom .ol-zoom-out {
    border-radius: 0 0 2px 2px;
  }

  .ol-attribution {
    text-align: right;
    bottom: .5em;
    right: .5em;
    max-width: calc(100% - 1.3em);
    display: flex;
    flex-flow: row-reverse;
    align-items: center;
  }

  .ol-attribution a {
    color: var(--ol-subtle-foreground-color);
    text-decoration: none;
  }

  .ol-attribution ul {
    margin: 0;
    padding: 1px .5em;
    color: var(--ol-foreground-color);
    text-shadow: 0 0 2px var(--ol-background-color);
    font-size: 12px;
  }

  .ol-attribution li {
    display: inline;
    list-style: none;
  }

  .ol-attribution li:not(:last-child):after {
    content: " ";
  }

  .ol-attribution img {
    max-height: 2em;
    max-width: inherit;
    vertical-align: middle;
  }

  .ol-attribution button {
    flex-shrink: 0;
  }

  .ol-attribution.ol-collapsed ul {
    display: none;
  }

  .ol-attribution:not(.ol-collapsed) {
    background: var(--ol-partial-background-color);
  }

  .ol-attribution.ol-uncollapsible {
    bottom: 0;
    right: 0;
    border-radius: 4px 0 0;
  }

  .ol-attribution.ol-uncollapsible img {
    margin-top: -.2em;
    max-height: 1.6em;
  }

  .ol-attribution.ol-uncollapsible button {
    display: none;
  }

  .ol-zoomslider {
    top: 4.5em;
    left: .5em;
    height: 200px;
  }

  .ol-zoomslider button {
    position: relative;
    height: 10px;
  }

  .ol-touch .ol-zoomslider {
    top: 5.5em;
  }

  .ol-overviewmap {
    left: 0.5em;
    bottom: 0.5em;
  }

  .ol-overviewmap.ol-uncollapsible {
    bottom: 0;
    left: 0;
    border-radius: 0 4px 0 0;
  }

  .ol-overviewmap .ol-overviewmap-map,
  .ol-overviewmap button {
    display: block;
  }

  .ol-overviewmap .ol-overviewmap-map {
    border: 1px solid var(--ol-subtle-foreground-color);
    height: 150px;
    width: 150px;
  }

  .ol-overviewmap:not(.ol-collapsed) button {
    bottom: 0;
    left: 0;
    position: absolute;
  }

  .ol-overviewmap.ol-collapsed .ol-overviewmap-map,
  .ol-overviewmap.ol-uncollapsible button {
    display: none;
  }

  .ol-overviewmap:not(.ol-collapsed) {
    background: var(--ol-subtle-background-color);
  }

  .ol-overviewmap-box {
    border: 1.5px dotted var(--ol-subtle-foreground-color);
  }

  .ol-overviewmap .ol-overviewmap-box:hover {
    cursor: move;
  }

  /* mapz */

  /* mapz style for controls */

  .ol-control,
  .ol-control:hover,
  .ol-control:focus {
    border-radius: 2px;
    background-color: inherit;
  }

  .ol-control button,
  .ol-control button:hover,
  .ol-control button:focus {
    background-color: rgba(39, 44, 49, 0.9);
    color: white;
  }

  /* mapz style for attribution */

  .ol-attribution,
  .ol-attribution:hover {
    background-clip: padding-box;
    border-radius: 4px;
  }

  .ol-attribution:not(.ol-collapsed) {
    background-color: rgba(255, 255, 255, 0.85);
  }

  .ol-attribution:not(.ol-collapsed) > ul > li {
    font-size: 11px;
  }

  .ol-attribution:not(.ol-collapsed) > ul > li > a {
    color: #464646;
    font-weight: 600;
  }

  .ol-attribution.ol-control button span {
    color: #fff;
  }

  .ol-attribution.ol-uncollapsible {
    margin: 0 10px 10px 0;
    border-radius: 3px;
    padding: 5px;
    box-sizing: content-box;
  }

  .ol-attribution.ol-uncollapsible > ul {
    padding: 0;
  }

  /* ol.mapz.control.Filesearch */

  [hidden] {
    display: none!important;
  }

  .mapz-control-search {
    margin: 8px;
    width: 40%;
    min-width: 25em;
    position: inherit;
  }

  .aa-Form {
    display: flex;
  }

  .aa-InputWrapperPrefix {
    display: none;
  }

  .aa-InputWrapper {
    position: relative;
    width: 100%;
  }

  .aa-Input {
    border: 0;
    font: inherit;
    height: 2em;
    padding: 0;
    width: 100%;
    font-size: 16px;
    font-weight: bold;
    border-radius: 4px;
    color: rgb(70, 70, 70);
    padding: 0 0.5em;
    background: white;
  }

  .aa-Input:focus {
    border-color: none;
    box-shadow: none;
    outline: none;
  }

  .aa-Input::-webkit-search-decoration,
  .aa-Input::-webkit-search-cancel-button,
  .aa-Input::-webkit-search-results-button,
  .aa-Input::-webkit-search-results-decoration {
  -webkit-appearance: none;
  appearance: none;
  }

  .aa-InputWrapperSuffix {
    align-items: center;
    display: flex;
    height: 2em;
  }

  .aa-InputWrapperSuffix .aa-ClearButton {
    margin: 0 0 0 8px;
  }

  .aa-InputWrapperSuffix .aa-ClearButton .aa-ClearIcon {
    fill: white;
  }

  .aa-Panel {
    margin: 8px 0 0 0;
    background: white;
  }

  .aa-PanelLayout {
    height: 100%;
    margin: 0;
    overflow-y: auto;
    padding: 8px;
    position: relative;
    text-align: left;
  }

  .aa-Panel--scrollable {
    margin: 0;
    max-height: 30vh;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-color: white #eaeaea;
    scrollbar-width: thin;
  }

  .aa-List {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
  }

  .aa-Item {
    cursor: pointer;
    padding: 0.2em;
  }

  /* ol.mapz.control.Geolocate */

  .mapz-control-geolocate {
    top: 4em;
    left: 0.5em;
  }

  button.mapz-control-geolocate-button {
    background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgYmFzZVByb2ZpbGU9InRpbnkiIGhlaWdodD0iMjRweCIgaWQ9IkxheWVyXzEiIHZlcnNpb249IjEuMiIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGc+PHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTEwLjM2OCwxOS4xMDJjMC4zNDksMS4wNDksMS4wMTEsMS4wODYsMS40NzgsMC4wODZsNS4zMDktMTEuMzc1YzAuNDY3LTEuMDAyLDAuMDM0LTEuNDM0LTAuOTY3LTAuOTY3TDQuODEyLDEyLjE1NCAgIGMtMS4wMDEsMC40NjctMC45NjMsMS4xMjksMC4wODUsMS40NzlMOSwxNUwxMC4zNjgsMTkuMTAyeiIvPjwvZz48L3N2Zz4=');
    background-size: 1.375em;
  }

  /* ol.mapz.controls.GeoTracker */

  .mapz-control-geotracker {
    top: 4em;
    left: 0.5em;
  }

  button.mapz-control-geotracker-button {
    background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgYmFzZVByb2ZpbGU9InRpbnkiIGhlaWdodD0iMjRweCIgaWQ9IkxheWVyXzEiIHZlcnNpb249IjEuMiIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGc+PHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTEwLjM2OCwxOS4xMDJjMC4zNDksMS4wNDksMS4wMTEsMS4wODYsMS40NzgsMC4wODZsNS4zMDktMTEuMzc1YzAuNDY3LTEuMDAyLDAuMDM0LTEuNDM0LTAuOTY3LTAuOTY3TDQuODEyLDEyLjE1NCAgIGMtMS4wMDEsMC40NjctMC45NjMsMS4xMjksMC4wODUsMS40NzlMOSwxNUwxMC4zNjgsMTkuMTAyeiIvPjwvZz48L3N2Zz4=');
    background-size: 1.375em;
  }

  /* ol.mapz.control.LayerSwitcher */

  .mapz-control-layerswitcher,
  .mapz-control-layerswitcher:hover {
    top: 0.5em;
    right: 0.5em;
    text-align: left;
    padding: 0;
    background-color: rgba(39, 44, 49, 0.9);
  }

  .mapz-control-layerswitcher .heading-container {
    display: flex;
  }

  .mapz-control-layerswitcher .heading-container .title {
    color: white;
    font-size: 0.9em;
    font-weight: bold;
    display: inline-flex;
    align-items: center;
    padding: 0.5em 1em;
    width: 100%;
  }

  .mapz-control-layerswitcher .heading-container .title.closed {
    display: none;
  }

  .mapz-control-layerswitcher .heading-container .toggle-button,
  .mapz-control-layerswitcher .heading-container .toggle-button:hover {
    color: white;
    background-color: transparent;
    flex-shrink: 0;
  }

  .mapz-control-layerswitcher .heading-container .toggle-button::before {
    content: 'x';
  }

  .mapz-control-layerswitcher .heading-container .toggle-button.closed::before {
    content: unset;
  }

  .mapz-control-layerswitcher .heading-container .toggle-button.closed {
    display: block;
    background-image: url('data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjIgMjIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0id2hpdGUiPjxwYXRoIHBvaW50cz0iNDgwIDE1MCAyNTYgNDggMzIgMTUwIDI1NiAyNTQgNDgwIDE1MCIgZD0iTTIwLjYyNSA2LjQ0NUwxMSAyLjA2M0wxLjM3NSA2LjQ0NUwxMSAxMC45MTRMMjAuNjI1IDYuNDQ1WiIvPjxwYXRoIHBvaW50cz0iMjU1LjcxIDM5Mi45NSAxMTAuOSAzMjYuNzUgMzIgMzYyIDI1NiA0NjQgNDgwIDM2MiA0MDEuMzEgMzI2LjcgMjU1LjcxIDM5Mi45NSIgZD0iTTEwLjk4OCAxNi44ODVMNC43NjUgMTQuMDRMMS4zNzUgMTUuNTU1TDExIDE5LjkzOEwyMC42MjUgMTUuNTU1TDE3LjI0NCAxNC4wMzhMMTAuOTg4IDE2Ljg4NVoiLz48cGF0aCBkPSJNMjAuNjI1IDExbC0zLjI0NSAtMS40NDFMMTEuMDA0IDEyLjQ4NyA0LjYxMiA5LjU1OCAxLjM3NSAxMSAxMSAxNS4zODMgMjAuNjI1IDExUzIwLjYyNSAxMSAyMC42MjUgMTFaIi8+PC9zdmc+');
    background-color: rgba(39, 44, 49, 0.9);
  }

  .mapz-control-layerswitcher .layers-container {
    margin-top: 0px;
    padding: 0.5em 0.75em 0.5em 0.75em;
    -moz-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    -o-user-select: none;
  }


  .mapz-control-layerswitcher .layers-container::empty {
      padding: 0;
  }

  .mapz-control-layerswitcher .layers-container.closed {
    display: none;
  }

  .mapz-control-layerswitcher input {
    margin: 0.2em 0.7em 0.2em 0;
    font-size: 0.75em;
    cursor: pointer;
    vertical-align: middle;
  }

  .mapz-control-layerswitcher label {
    cursor: pointer;
  }

  .mapz-control-layerswitcher span {
    color: white;
    font-weight: bold;
    font-size: 0.75em;
  }

  /* ol.mapz.control.Search */

  .mapz-control-search {
    margin: 8px;
    width: 40%;
  }

  .mapz-control-search input {
    border: 0;
    font: inherit;
    height: 2em;
    padding: 0;
    width: 100%;
    font-size: 16px;
    font-weight: bold;
    border-radius: 4px;
    color: rgb(70, 70, 70);
    padding: 0 0.5em;
    background: white;
  }

  .mapz-control-search input:focus {
    border-color: none;
    box-shadow: none;
    outline: none;
  }

  .search-input-container.nominatim {
    display: flex;
  }

  .mapz-control-search .search-suffix-container {
    align-items: center;
    display: flex;
    height: 2em;
  }

  .mapz-control-search .search-suffix-container .clear-button {
    margin: 0 0 0 8px;
  }

  .search-input-container .search-suffix-container .requesting {
    background-image: url('data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==');
    background-position: center;
    background-color: rgba(39, 44, 49, 0.9);
    margin: 0 0 0 8px;
    width: 1.375em;
    height: 1.375em;
  }

  .search-input-container .search-suffix-container .clear-button {
    background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgYmFzZVByb2ZpbGU9InRpbnkiIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZlcnNpb249IjEuMiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJ3aGl0ZSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGc+PHBhdGggZD0iTTUuMjkzIDYuNzA3bDUuMjkzIDUuMjkzLTUuMjkzIDUuMjkzYy0wLjM5MSAwLjM5MS0wLjM5MSAxLjAyNCAwIDEuNDE0czEuMDI0IDAuMzkxIDEuNDE0IDBsNS4yOTMtNS4yOTMgNS4yOTMgNS4yOTNjMC4zOTEgMC4zOTEgMS4wMjQgMC4zOTEgMS40MTQgMHMwLjM5MS0xLjAyNCAwLTEuNDE0bC01LjI5My01LjI5MyA1LjI5My01LjI5M2MwLjM5MS0wLjM5MSAwLjM5MS0xLjAyNCAwLTEuNDE0cy0xLjAyNC0wLjM5MS0xLjQxNCAwbC01LjI5MyA1LjI5My01LjI5My01LjI5M2MtMC4zOTEtMC4zOTEtMS4wMjQtMC4zOTEtMS40MTQgMHMtMC4zOTEgMS4wMjQgMCAxLjQxNHoiLz48L2c+PC9zdmc+');
    background-position: center;
  }

  .mapz-control-search .search-results {
    margin-top: 0.3em;
    background-clip: padding-box;
    background-color: white;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    box-shadow: 0 2px 4px 0 rgba(169, 169, 169, 0.5);
    height: auto;
    max-height: 30vh;
    overflow-y: auto;
    padding: 5px 5px;
    width: 95%;
    box-sizing: border-box;
    font-family: "HelveticaNeue", "Helvetica";
  }

  .ol-control.mapz-control-search .search-results {
    position: relative;
  }

  .search-results div {
    background-color: none;
    padding: 5px 5px;
    cursor: pointer;
    margin: 5px 5px;
    border-bottom: 1px solid  #d9d9d9;
    color: #464646;
    font-size: 16px;
  }

  .search-results div span.name,
  .search-results div span.description {
    display: block;
  }

  .search-results div:hover {
    background-color: #f2f2f2;
    border-radius: 4px;
  }

  .search-results div.no-results,
  .search-results div.no-results:hover {
    border: 0;
  }

  /* ol.mapz.control.Modal */

  .mapz-control-modal, 
  .mapz-control-modal:focus,
  .mapz-control-modal:hover {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    background-color: rgba(0, 0, 0, 0.5);
  }

  .mapz-control-modal-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(254, 254, 254, 0.9);
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    box-shadow: 0 2px 8px 0 rgba(169, 169, 169, 0.5);
    padding: 30px 30px;
    width: 50%;
    min-height: 30%;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .mapz-control-modal-message {
    text-align: center;
  }
</style>