Visualization of various data formats on the map
vanilla.html
react.html
vue.html
common.css
common.ts
features.json
features.gpx
features.kml
gpxToGeojson.ts
kmlToGeojson.ts
variables.ts
<!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"></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;
}