Visualization of various data formats on the map

Open in CodeSandbox

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../kmlToGeojson.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../gpxToGeojson.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import {POLYGON_STYLE, LOCATION, MARKER_PROPS, TOOLTIP_TEXT, loadGeometries} from '../variables';

      window.map = null;

      interface InfoMessageProps {
          text: string;
      }

      main();
      async function main() {
          // Waiting for all api elements to be loaded
          await mappable.ready;
          const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature, MMapControls} = mappable;
          const {MMapPopupMarker} = await mappable.import('@mappable-world/mappable-default-ui-theme');
          const geometries = await loadGeometries();

          class InfoMessage extends mappable.MMapComplexEntity<InfoMessageProps> {
              private _element!: HTMLDivElement;
              private _detachDom!: () => void;

              // Method for create a DOM control element
              _createElement(props: InfoMessageProps) {
                  // Create a root element
                  const infoWindow = document.createElement('div');
                  infoWindow.classList.add('info-window');
                  infoWindow.innerHTML = props.text;

                  return infoWindow;
              }

              // Method for attaching the control to the map
              _onAttach() {
                  this._element = this._createElement(this._props);
                  this._detachDom = mappable.useDomContext(this, this._element, this._element);
              }

              // Method for detaching control from the map
              _onDetach() {
                  this._detachDom();
                  this._detachDom = undefined;
                  this._element = undefined;
              }
          }

          function PopupContent(markerProp: {format: string}) {
              const textElement = document.createElement('div');
              textElement.classList.add('text');
              const darkText = document.createElement('span');
              darkText.classList.add('dark');
              darkText.innerText = markerProp.format;
              const text = document.createElement('span');
              text.innerText = ' format';

              textElement.appendChild(darkText);
              textElement.appendChild(text);
              return textElement;
          }

          // Initialize the map
          map = new MMap(
              // Pass the link to the HTMLElement of the container
              document.getElementById('app'),
              // Pass the map initialization parameters
              {location: LOCATION, showScaleInCopyrights: true},
              [
                  // Add a map scheme layer
                  new MMapDefaultSchemeLayer({}),
                  // Add a layer of geo objects to display the line
                  new MMapDefaultFeaturesLayer({})
              ]
          );

          geometries.forEach((geometry) => {
              // Create a line object, set its coordinates and styles, and add it to the map
              const feature = new MMapFeature({
                  geometry: geometry,
                  style: POLYGON_STYLE
              });
              map.addChild(feature);
          });

          MARKER_PROPS.forEach((markerProp) => {
              const marker = new MMapPopupMarker({
                  coordinates: markerProp.coordinates,
                  position: markerProp.position,
                  content: () => PopupContent(markerProp)
              });
              map.addChild(marker);
          });

          /* Create and add a shared container for controls to the map.
        Using MMapControls you can change the position of the control */
          const topRightControls = new MMapControls({position: 'top left'});
          map.addChild(topRightControls);

          // Add a custom information message control to the map
          topRightControls.addChild(new InfoMessage({text: TOOLTIP_TEXT}));
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../kmlToGeojson.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../gpxToGeojson.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
      import {POLYGON_STYLE, LOCATION, MARKER_PROPS, TOOLTIP_TEXT, loadGeometries} from '../variables';
      import {PolygonGeometry} from '@mappable-world/mappable-types';

      window.map = null;

      main();
      async function main() {
          // For each object in the JS API, there is a React counterpart
          // To use the React version of the API, include the module @mappable-world/mappable-reactify
          const [mappableReact] = await Promise.all([mappable.import('@mappable-world/mappable-reactify'), mappable.ready]);
          const reactify = mappableReact.reactify.bindTo(React, ReactDOM);
          const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature, MMapControls, MMapControl} =
              reactify.module(mappable);
          const {MMapPopupMarker} = reactify.module(await mappable.import('@mappable-world/mappable-default-ui-theme'));

          const {useEffect, useState, useCallback} = React;

          function App() {
              const [geometries, setGeometries] = useState([]);

              useEffect(() => {
                  async function getData() {
                      const geometries = await loadGeometries();
                      setGeometries(geometries);
                  }
                  getData();
              }, []);

              const PopupContent = useCallback((markerProp: {format: string}) => {
                  return (
                      <div className="text">
                          <span className="dark">{markerProp.format}</span> format
                      </div>
                  );
              }, []);

              return (
                  // Initialize the map and pass initialization parameters
                  <MMap location={LOCATION} showScaleInCopyrights={true} ref={(x) => (map = x)}>
                      {/* Add a map scheme layer */}
                      <MMapDefaultSchemeLayer />
                      {/* Add a layer of geo objects to display the line */}
                      <MMapDefaultFeaturesLayer />

                      {/* Add a line object to the map, set its coordinates and styles */}
                      {geometries.map((geometry) => (
                          <MMapFeature geometry={geometry as PolygonGeometry} style={POLYGON_STYLE} />
                      ))}

                      {MARKER_PROPS.map((markerProp) => (
                          <MMapPopupMarker
                              coordinates={markerProp.coordinates}
                              position={markerProp.position}
                              content={() => PopupContent(markerProp)}
                          />
                      ))}

                      {/* Add a shared container for controls to the map.
                      Using MMapControls you can change the position of the control */}
                      <MMapControls position="top left">
                          {/* Add a custom information message control to the map */}
                          <MMapControl transparent>
                              <div className="info-window">{TOOLTIP_TEXT}</div>
                          </MMapControl>
                      </MMapControls>
                  </MMap>
              );
          }

          ReactDOM.render(
              <React.StrictMode>
                  <App />
              </React.StrictMode>,
              document.getElementById('app')
          );
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../kmlToGeojson.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../gpxToGeojson.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import {POLYGON_STYLE, LOCATION, TOOLTIP_TEXT, MARKER_PROPS, loadGeometries} from '../variables';

      window.map = null;

      async function main() {
        const [mappableVue] = await Promise.all([mappable.import('@mappable-world/mappable-vuefy'), mappable.ready]);
        const vuefy = mappableVue.vuefy.bindTo(Vue);
        const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature, MMapControls, MMapControl} =
          vuefy.module(mappable);
        const {MMapPopupMarker} = vuefy.module(await mappable.import('@mappable-world/mappable-default-ui-theme'));

        const App = Vue.createApp({
          components: {
            MMap,
            MMapDefaultSchemeLayer,
            MMapDefaultFeaturesLayer,
            MMapFeature,
            MMapControls,
            MMapControl,
            MMapPopupMarker
          },
          setup() {
            const refMap = (ref) => {
              window.map = ref?.entity;
            };
            const geometries = Vue.ref([]);

            Vue.onMounted(async () => {
              geometries.value = await loadGeometries();
            });

            return {
              refMap,
              LOCATION,
              POLYGON_STYLE,
              TOOLTIP_TEXT,
              MARKER_PROPS,
              geometries
            };
          },
          template: `
      <MMap
        :location="LOCATION"
        :ref="refMap"
        :showScaleInCopyrights="true"
      >
        <MMapDefaultSchemeLayer/>
        <MMapDefaultFeaturesLayer/>

        <template v-for="geometry of geometries">
          <MMapFeature
            :geometry="geometry"
            :style="POLYGON_STYLE"
          />
        </template>

        <template v-for="markerProp of MARKER_PROPS">
          <MMapPopupMarker :coordinates="markerProp.coordinates" :position="markerProp.position">
            <template #content>
              <div class="text">
                <span class="dark">{{ markerProp.format }}</span> format
              </div>
            </template>
          </MMapPopupMarker>
        </template>

        <MMapControls position="top left">
          <MMapControl :transparent="true">
            <div class="info-window">
              {{ TOOLTIP_TEXT }}
            </div>
          </MMapControl>
        </MMapControls>
      </MMap>
    `
        });

        App.mount('#app');
      }

      main();
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
.info-window {
  padding: 8px 12px 8px 40px;
  border-radius: 12px;
  background-color: #313133;
  background-image: url('./info-icon.svg');
  background-position: 10px 8px;
  background-repeat: no-repeat;
  color: #f2f5fa;
  font-size: 14px;
  line-height: 20px;
  min-width: max-content;
}

.text {
  color: rgba(123, 125, 133);
  font-weight: 500;
}

.dark {
  color: rgba(5, 13, 51, 1);
}
import {LngLat} from '@mappable-world/mappable-types';

mappable.ready.then(() => {
  mappable.import.registerCdn(
    'https://cdn.jsdelivr.net/npm/{package}',
    '@mappable-world/mappable-default-ui-theme@0.0'
  );
});

export const GEOMETRY_TYPES = ['Polygon', 'MultiPolygon', 'LineString', 'MultiLineString', 'Point'];

function convertToArray(coordinates: LngLat[]) {
  return [coordinates];
}
function convertToMultiArray(coordinates: LngLat[]) {
  return [[coordinates]];
}

export const GEOMETRY_TYPE_CONVERTERS = {
  Polygon: convertToArray,
  Point: (coordinates: LngLat) => coordinates,
  LineString: (coordinates: LngLat) => coordinates,
  MultiLineString: convertToArray,
  MultiPolygon: convertToMultiArray
};
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [54.592626028648, 24.479029576020665],
            [54.59236957945173, 24.479018109707262],
            [54.59211560014048, 24.478983821200167],
            [54.59186653680757, 24.478927040734902],
            [54.5916247881923, 24.47884831516836],
            [54.591392682573996, 24.47874840271113],
            [54.5911724553453, 24.47862826562395],
            [54.59096622748066, 24.478489060948725],
            [54.59077598510771, 24.478332129363423],
            [54.59060356037819, 24.478158982268283],
            [54.59045061382281, 24.477971287227774],
            [54.590318618359895, 24.47777085190858],
            [54.590208845112045, 24.47755960666847],
            [54.590122351167, 24.477339585963733],
            [54.590059969400706, 24.477112908754375],
            [54.590022300460426, 24.476881758095796],
            [54.59000970698493, 24.47664836011365],
            [54.590022310117234, 24.476414962564327],
            [54.59005998834322, 24.476183813187568],
            [54.590122378667274, 24.475957138059773],
            [54.59020888011325, 24.475737120156353],
            [54.59031865951695, 24.475525878329663],
            [54.59045065955408, 24.475325446904797],
            [54.590603608926266, 24.475137756089886],
            [54.5907760346069, 24.47496461338923],
            [54.59096627602872, 24.474807686198403],
            [54.59117250107658, 24.47466848574878],
            [54.591392723731055, 24.47454835255593],
            [54.59162482319351, 24.474448443512117],
            [54.591866564307836, 24.474369720746893],
            [54.592115619082996, 24.47431294236319],
            [54.592369589108536, 24.474278655137915],
            [54.592626028648, 24.474267189257336],
            [54.592882468187454, 24.474278655137915],
            [54.59313643821301, 24.47431294236319],
            [54.593385492988155, 24.474369720746893],
            [54.59362723410249, 24.474448443512117],
            [54.593859333564936, 24.47454835255593],
            [54.59407955621943, 24.47466848574878],
            [54.59428578126727, 24.474807686198403],
            [54.5944760226891, 24.47496461338923],
            [54.59464844836973, 24.475137756089886],
            [54.59480139774192, 24.475325446904797],
            [54.59493339777904, 24.475525878329663],
            [54.59504317718274, 24.475737120156353],
            [54.595129678628716, 24.475957138059773],
            [54.59519206895277, 24.476183813187568],
            [54.59522974717877, 24.476414962564327],
            [54.59524235031106, 24.47664836011365],
            [54.595229756835565, 24.476881758095796],
            [54.59519208789529, 24.477112908754375],
            [54.59512970612899, 24.477339585963733],
            [54.595043212183946, 24.47755960666847],
            [54.5949334389361, 24.47777085190858],
            [54.59480144347319, 24.477971287227774],
            [54.5946484969178, 24.478158982268283],
            [54.59447607218828, 24.478332129363423],
            [54.59428582981534, 24.478489060948725],
            [54.59407960195069, 24.47862826562395],
            [54.593859374722, 24.47874840271113],
            [54.59362726910369, 24.47884831516836],
            [54.593385520488425, 24.478927040734902],
            [54.593136457155516, 24.478983821200167],
            [54.59288247784427, 24.479018109707262],
            [54.592626028648, 24.479029576020665]
          ]
        ]
      }
    }
  ]
}
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="togpx"><trk><name></name><desc></desc><trkseg><trkpt lat="24.46997" lon="54.605463"/><trkpt lat="24.470262" lon="54.60783"/><trkpt lat="24.4703" lon="54.607955"/><trkpt lat="24.470389" lon="54.608049"/><trkpt lat="24.470512" lon="54.608114"/><trkpt lat="24.470634" lon="54.608126"/><trkpt lat="24.470762" lon="54.608091"/><trkpt lat="24.472228" lon="54.607712"/><trkpt lat="24.472388" lon="54.607647"/><trkpt lat="24.472506" lon="54.607558"/><trkpt lat="24.472619" lon="54.60741"/><trkpt lat="24.472675" lon="54.607286"/><trkpt lat="24.472865" lon="54.606615"/><trkpt lat="24.472968" lon="54.606392"/><trkpt lat="24.473071" lon="54.606226"/><trkpt lat="24.4732" lon="54.606076"/><trkpt lat="24.473321" lon="54.605963"/><trkpt lat="24.473422" lon="54.605879"/><trkpt lat="24.473644" lon="54.605777"/><trkpt lat="24.473813" lon="54.60574"/><trkpt lat="24.473997" lon="54.605737"/><trkpt lat="24.474215" lon="54.605778"/><trkpt lat="24.474444" lon="54.605854"/><trkpt lat="24.475027" lon="54.606021"/><trkpt lat="24.475459" lon="54.60608"/><trkpt lat="24.475766" lon="54.606086"/><trkpt lat="24.476032" lon="54.606056"/><trkpt lat="24.4774" lon="54.605871"/><trkpt lat="24.478262" lon="54.605748"/><trkpt lat="24.478362" lon="54.605724"/><trkpt lat="24.478443" lon="54.605701"/><trkpt lat="24.478526" lon="54.60563"/><trkpt lat="24.478617" lon="54.605509"/><trkpt lat="24.47864" lon="54.605436"/><trkpt lat="24.478648" lon="54.605352"/><trkpt lat="24.478636" lon="54.605272"/><trkpt lat="24.478605" lon="54.605186"/><trkpt lat="24.478546" lon="54.605122"/><trkpt lat="24.478491" lon="54.605083"/><trkpt lat="24.478399" lon="54.605034"/><trkpt lat="24.478001" lon="54.604887"/><trkpt lat="24.477425" lon="54.604747"/><trkpt lat="24.474212" lon="54.603563"/><trkpt lat="24.472968" lon="54.603101"/><trkpt lat="24.472274" lon="54.602845"/><trkpt lat="24.471736" lon="54.602653"/><trkpt lat="24.471068" lon="54.602453"/><trkpt lat="24.469838" lon="54.60203"/><trkpt lat="24.46873" lon="54.601627"/><trkpt lat="24.468622" lon="54.60158"/><trkpt lat="24.468541" lon="54.601568"/><trkpt lat="24.468494" lon="54.60158"/><trkpt lat="24.468447" lon="54.601625"/><trkpt lat="24.468444" lon="54.601727"/><trkpt lat="24.468485" lon="54.602104"/><trkpt lat="24.468485" lon="54.602187"/><trkpt lat="24.468412" lon="54.602254"/><trkpt lat="24.467672" lon="54.602468"/><trkpt lat="24.467533" lon="54.602512"/><trkpt lat="24.467226" lon="54.602647"/><trkpt lat="24.467006" lon="54.60277"/><trkpt lat="24.466655" lon="54.603035"/><trkpt lat="24.466335" lon="54.603337"/><trkpt lat="24.466038" lon="54.603717"/><trkpt lat="24.464881" lon="54.605328"/><trkpt lat="24.46461" lon="54.605695"/><trkpt lat="24.464422" lon="54.605984"/><trkpt lat="24.464195" lon="54.60637"/><trkpt lat="24.464021" lon="54.606701"/><trkpt lat="24.463786" lon="54.607236"/><trkpt lat="24.463586" lon="54.607725"/><trkpt lat="24.463273" lon="54.608452"/><trkpt lat="24.463159" lon="54.608763"/><trkpt lat="24.463158" lon="54.608938"/><trkpt lat="24.463192" lon="54.609123"/><trkpt lat="24.463281" lon="54.609292"/><trkpt lat="24.46336" lon="54.609382"/><trkpt lat="24.463438" lon="54.609442"/><trkpt lat="24.463553" lon="54.609502"/><trkpt lat="24.463665" lon="54.609536"/><trkpt lat="24.463769" lon="54.609556"/><trkpt lat="24.463941" lon="54.60954"/><trkpt lat="24.464066" lon="54.609502"/><trkpt lat="24.464187" lon="54.609448"/><trkpt lat="24.464295" lon="54.609369"/><trkpt lat="24.464393" lon="54.609257"/><trkpt lat="24.464478" lon="54.609118"/><trkpt lat="24.464537" lon="54.608971"/><trkpt lat="24.464565" lon="54.608757"/><trkpt lat="24.464689" lon="54.607061"/><trkpt lat="24.464714" lon="54.606852"/><trkpt lat="24.464732" lon="54.606762"/><trkpt lat="24.464763" lon="54.606667"/><trkpt lat="24.465281" lon="54.605756"/><trkpt lat="24.465344" lon="54.605664"/><trkpt lat="24.465416" lon="54.605602"/><trkpt lat="24.46557" lon="54.605536"/><trkpt lat="24.466473" lon="54.605324"/><trkpt lat="24.466544" lon="54.605338"/><trkpt lat="24.466592" lon="54.605387"/><trkpt lat="24.466611" lon="54.605461"/><trkpt lat="24.466714" lon="54.606217"/><trkpt lat="24.466748" lon="54.606306"/><trkpt lat="24.466775" lon="54.606363"/><trkpt lat="24.466831" lon="54.606423"/><trkpt lat="24.466934" lon="54.606483"/><trkpt lat="24.467061" lon="54.606497"/><trkpt lat="24.467686" lon="54.606499"/><trkpt lat="24.467793" lon="54.606444"/><trkpt lat="24.467857" lon="54.606376"/><trkpt lat="24.467893" lon="54.606273"/><trkpt lat="24.467921" lon="54.606132"/><trkpt lat="24.467936" lon="54.606009"/><trkpt lat="24.467941" lon="54.605845"/><trkpt lat="24.46793" lon="54.605683"/><trkpt lat="24.467709" lon="54.604105"/><trkpt lat="24.4677" lon="54.603969"/><trkpt lat="24.467706" lon="54.603796"/><trkpt lat="24.467733" lon="54.603627"/><trkpt lat="24.467768" lon="54.603511"/><trkpt lat="24.467832" lon="54.603434"/><trkpt lat="24.46791" lon="54.603354"/><trkpt lat="24.468626" lon="54.602921"/><trkpt lat="24.468955" lon="54.602697"/><trkpt lat="24.469052" lon="54.60265"/><trkpt lat="24.469181" lon="54.602617"/><trkpt lat="24.469291" lon="54.602606"/><trkpt lat="24.469423" lon="54.602604"/><trkpt lat="24.469513" lon="54.602628"/><trkpt lat="24.469578" lon="54.602686"/><trkpt lat="24.469611" lon="54.602758"/><trkpt lat="24.469638" lon="54.602923"/><trkpt lat="24.46997" lon="54.605463"/></trkseg></trk></gpx>
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <Placemark>
      <Polygon>
        <outerBoundaryIs>
          <LinearRing>
            <coordinates>
              54.614681029093504,24.476305846538256,0
              54.61437961053829,24.476292369225973,0
              54.614081095000635,24.47625206709162,0
              54.61378835753306,24.476185328292274,0
              54.613504217527634,24.47609279560048,0
              54.61323141155714,24.475975360212352,0
              54.612972567014644,24.475834153162797,0
              54.612730176805584,24.47567053443035,0
              54.61250657533616,24.47548607983691,0
              54.612303916029695,24.475282565868458,0
              54.61212415058715,24.475061952563173,0
              54.61196901019194,24.474826364631845,0
              54.61183998883988,24.474578070992493,0
              54.61173832895468,24.474319462916476,0
              54.61166500942737,24.474053030996668,0
              54.611620736194844,24.47378134115948,0
              54.61160593544786,24.47350700995207,0
              54.61162074953363,24.47323267934251,0
              54.61166503559231,24.472960991275926,0
              54.61173836694028,24.472694562231414,0
              54.6118400371864,24.472435958024903,0
              54.61196906704142,24.472187669100553,0
              54.61212421375491,24.471952086548526,0
              54.61230398308823,24.47173147908013,0
              54.61250664370845,24.471527971181843,0
              54.61273024386411,24.471343522658564,0
              54.612972630182405,24.471179909763002,0
              54.61323146840662,24.471038708092753,0
              54.61350426587414,24.47092127741963,0
              54.613788395518675,24.470828748597338,0
              54.614081121165576,24.470762012673294,0
              54.61437962387706,24.470721712309537,0
              54.614681029093504,24.47070823559511,0
              54.614982434309944,24.470721712309537,0
              54.61528093702143,24.470762012673294,0
              54.61557366266834,24.470828748597338,0
              54.615857792312866,24.47092127741963,0
              54.6161305897804,24.471038708092753,0
              54.61638942800461,24.471179909763002,0
              54.61663181432291,24.471343522658564,0
              54.61685541447856,24.471527971181843,0
              54.617058075098775,24.47173147908013,0
              54.617237844432104,24.471952086548526,0
              54.61739299114559,24.472187669100553,0
              54.61752202100062,24.472435958024903,0
              54.61762369124672,24.472694562231414,0
              54.6176970225947,24.472960991275926,0
              54.617741308653386,24.47323267934251,0
              54.617756122739145,24.47350700995207,0
              54.617741321992156,24.47378134115948,0
              54.617697048759645,24.474053030996668,0
              54.617623729232335,24.474319462916476,0
              54.61752206934713,24.474578070992493,0
              54.61739304799507,24.474826364631845,0
              54.617237907599865,24.475061952563173,0
              54.617058142157305,24.475282565868458,0
              54.616855482850845,24.47548607983691,0
              54.61663188138143,24.47567053443035,0
              54.616389491172356,24.475834153162797,0
              54.61613064662987,24.475975360212352,0
              54.61585784065938,24.47609279560048,0
              54.615573700653954,24.476185328292274,0
              54.61528096318638,24.47625206709162,0
              54.614982447648714,24.476292369225973,0
              54.614681029093504,24.476305846538256,0
            </coordinates>
          </LinearRing>
        </outerBoundaryIs>
      </Polygon>
    </Placemark>
  </Document>
</kml>
export function gpxToGeoJSON(gpxString: string) {
  const parser = new DOMParser();
  const gpx = parser.parseFromString(gpxString, 'application/xml');
  const geojson = {
    type: 'FeatureCollection',
    features: []
  };

  const trksegs = gpx.getElementsByTagName('trkseg');

  for (let i = 0; i < trksegs.length; i++) {
    const trkseg = trksegs[i];
    const trkpts = trkseg.getElementsByTagName('trkpt');

    const coordinates = [];

    for (let j = 0; j < trkpts.length; j++) {
      const trkpt = trkpts[j];
      const lat = parseFloat(trkpt.getAttribute('lat'));
      const lon = parseFloat(trkpt.getAttribute('lon'));

      coordinates.push([lon, lat]);
    }

    const feature = {
      type: 'Feature',
      geometry: {
        type: 'Polygon',
        coordinates: [coordinates]
      },
      properties: {}
    };

    geojson.features.push(feature);
  }

  return geojson;
}
import {GEOMETRY_TYPES, GEOMETRY_TYPE_CONVERTERS} from './common';
import {LngLat} from '@mappable-world/mappable-types';

export function kmlToGeoJSON(kmlString: string) {
  const parser = new DOMParser();
  const kml = parser.parseFromString(kmlString, 'application/xml');
  const geojson = {
    type: 'FeatureCollection',
    features: []
  };

  const placemarks = kml.getElementsByTagName('Placemark');

  for (let i = 0; i < placemarks.length; i++) {
    const placemark = placemarks[i];
    const name = placemark.getElementsByTagName('name')[0]?.textContent || 'Unnamed';

    let geometryTypeName;
    for (const geometryType of GEOMETRY_TYPES) {
      const geometryTypeTag = placemark.getElementsByTagName(geometryType);
      if (geometryTypeTag[0]) {
        geometryTypeName = geometryTypeTag[0].nodeName;
      }
    }
    if (!geometryTypeName) {
      throw new Error('Geometry type not found!');
    }

    const coordinatesText = placemark.getElementsByTagName('coordinates')[0]?.textContent.trim();
    const coordinatesArray: LngLat[] = coordinatesText.split(/\s+/).map((coord) => {
      const [lng, lat, alt] = coord.split(',').map(Number);
      return [lng, lat];
    });

    const feature = {
      type: 'Feature',
      geometry: {
        type: geometryTypeName,
        coordinates: GEOMETRY_TYPE_CONVERTERS[geometryTypeName](coordinatesArray)
      },
      properties: {
        name: name
      }
    };

    geojson.features.push(feature);
  }

  return geojson;
}
import type {LngLat, MMapLocationRequest, DrawingStyle} from '@mappable-world/mappable-types';
import type {MMapPopupPositionProps} from '@mappable-world/mappable-default-ui-theme';
import {kmlToGeoJSON} from './kmlToGeojson';
import {gpxToGeoJSON} from './gpxToGeojson';

export const LOCATION: MMapLocationRequest = {
  center: [54.6056, 24.4715], // starting position [lng, lat]
  zoom: 15 // starting zoom
};

export const TOOLTIP_TEXT = 'Location: Yes Marina Circuit, 2/1, Abu Dhabi';
export const POLYGON_STYLE: DrawingStyle = {
  stroke: [{color: '#122db2', width: 3}],
  fill: '#122db2',
  fillOpacity: 0.1,
  simplificationRate: 0
};
export const MARKER_PROPS: Array<{coordinates: LngLat; format: string; position: MMapPopupPositionProps}> = [
  {
    coordinates: [54.5904, 24.4766],
    format: 'GeoJSON',
    position: 'left'
  },
  {
    coordinates: [54.6172, 24.474],
    format: 'KML',
    position: 'right'
  },
  {
    coordinates: [54.6033, 24.4729],
    format: 'GPX',
    position: 'left'
  }
];
export async function loadGeometries() {
  const geometries = [];

  const kmlText = await fetch('../features/kml/feature.kml').then((r) => r.text());
  const geoJsonKml = kmlToGeoJSON(kmlText);
  geometries.push(geoJsonKml.features[0].geometry);

  const gpxText = await fetch('../features/gpx/feature.gpx').then((r) => r.text());
  const geoJsonGpx = gpxToGeoJSON(gpxText);
  geometries.push(geoJsonGpx.features[0].geometry);

  const geojson = await fetch('../features/geojson/feature.json').then((r) => r.json());
  geometries.push(geojson.features[0].geometry);

  return geometries;
}