Zum Inhalt springen

Route

Die Routing-API arbeitet auf dem GIP.at-Netz für Fuß, Rad, Mountainbike und Auto. Die Antwort hat die Mapbox-Form routes[0] mit geometry (GeoJSON-Linie), distance in Metern und duration in Sekunden.

Start in die Karte klicken, dann das Ziel.

Code

// Route: click start and destination on the map, the Directions API returns a GeoJSON line.
const TOKEN = 'YOUR_TOKEN'; // your public token (mx_pk_…) from https://account.mapx.at
// Adds the token to every request MapLibre makes to mapx.at (style, tiles, fonts, sprites), never to other hosts.
const transformRequest = (url) => ({ url: /^https:\/\/([\w-]+\.)?mapx\.at\//.test(url) ? url + (url.includes('?') ? '&' : '?') + 'access_token=' + TOKEN : url });
const AUTH = { headers: { Authorization: 'Bearer ' + TOKEN } };

maplibregl.addProtocol('pmtiles', new pmtiles.Protocol().tile);

const map = new maplibregl.Map({ transformRequest, container: 'map', style: 'https://api.mapx.at/v1/styles/streets', center: [15.33, 48.23], zoom: 13 }); // Melk
map.addControl(new maplibregl.NavigationControl());
let a = null, b = null, markerA, markerB;

map.on('load', () => {
  map.addSource('route', { type: 'geojson', data: { type: 'FeatureCollection', features: [] } });
  map.addLayer({ id: 'route', type: 'line', source: 'route', layout: { 'line-cap': 'round', 'line-join': 'round' }, paint: { 'line-color': '#2346d8', 'line-width': 5 } });
});
map.on('click', async (e) => {
  if (a && b) { a = b = null; markerA?.remove(); markerB?.remove(); map.getSource('route').setData({ type: 'FeatureCollection', features: [] }); }
  const p = [e.lngLat.lng, e.lngLat.lat];
  if (!a) { a = p; markerA = new maplibregl.Marker({ color: '#1d7f4e' }).setLngLat(p).addTo(map); return; }
  b = p; markerB = new maplibregl.Marker({ color: '#c8372d' }).setLngLat(p).addTo(map);
  const profil = document.getElementById('profil').value; // walking, cycling, cycling-mtb or driving
  const url = `https://api.mapx.at/v1/directions/${profil}/${a.join(',')};${b.join(',')}?geometries=geojson&overview=full`;
  const info = document.getElementById('info');
  try {
    const r = await fetch(url, AUTH);
    if (!r.ok) throw new Error('no route (HTTP ' + r.status + ')');
    const route = (await r.json()).routes[0]; // Mapbox shape: routes[0].geometry is a GeoJSON line
    map.getSource('route').setData({ type: 'Feature', geometry: route.geometry, properties: {} });
    info.textContent = `${(route.distance / 1000).toFixed(2)} km, ${Math.round(route.duration / 60)} min`;
  } catch (err) { info.textContent = 'Error: ' + err.message; }
});

Vollständige HTML-Datei

Speichern und im Browser öffnen. Es braucht nur MapLibre GL JS 4.7.1 und pmtiles 3.2.1 per CDN, dazu den öffentlichen Token (YOUR_TOKEN ersetzen), keinen Build.

<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>mapx Beispiel</title>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css">
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/pmtiles@3.2.1/dist/pmtiles.js"></script>
<style>html,body{margin:0;font:14px system-ui,sans-serif}#map{height:70vh}</style>
</head>
<body>
<label>Verkehrsmittel <select id="profil"><option value="walking">zu Fuß</option><option value="cycling">Rad</option><option value="cycling-mtb">Mountainbike</option><option value="driving">Auto</option></select></label>
<div id="map"></div>
<p id="info">Start in die Karte klicken, dann das Ziel.</p>
<script>
// Route: click start and destination on the map, the Directions API returns a GeoJSON line.
const TOKEN = 'YOUR_TOKEN'; // your public token (mx_pk_…) from https://account.mapx.at
// Adds the token to every request MapLibre makes to mapx.at (style, tiles, fonts, sprites), never to other hosts.
const transformRequest = (url) => ({ url: /^https:\/\/([\w-]+\.)?mapx\.at\//.test(url) ? url + (url.includes('?') ? '&' : '?') + 'access_token=' + TOKEN : url });
const AUTH = { headers: { Authorization: 'Bearer ' + TOKEN } };

maplibregl.addProtocol('pmtiles', new pmtiles.Protocol().tile);

const map = new maplibregl.Map({ transformRequest, container: 'map', style: 'https://api.mapx.at/v1/styles/streets', center: [15.33, 48.23], zoom: 13 }); // Melk
map.addControl(new maplibregl.NavigationControl());
let a = null, b = null, markerA, markerB;

map.on('load', () => {
  map.addSource('route', { type: 'geojson', data: { type: 'FeatureCollection', features: [] } });
  map.addLayer({ id: 'route', type: 'line', source: 'route', layout: { 'line-cap': 'round', 'line-join': 'round' }, paint: { 'line-color': '#2346d8', 'line-width': 5 } });
});
map.on('click', async (e) => {
  if (a && b) { a = b = null; markerA?.remove(); markerB?.remove(); map.getSource('route').setData({ type: 'FeatureCollection', features: [] }); }
  const p = [e.lngLat.lng, e.lngLat.lat];
  if (!a) { a = p; markerA = new maplibregl.Marker({ color: '#1d7f4e' }).setLngLat(p).addTo(map); return; }
  b = p; markerB = new maplibregl.Marker({ color: '#c8372d' }).setLngLat(p).addTo(map);
  const profil = document.getElementById('profil').value; // walking, cycling, cycling-mtb or driving
  const url = `https://api.mapx.at/v1/directions/${profil}/${a.join(',')};${b.join(',')}?geometries=geojson&overview=full`;
  const info = document.getElementById('info');
  try {
    const r = await fetch(url, AUTH);
    if (!r.ok) throw new Error('no route (HTTP ' + r.status + ')');
    const route = (await r.json()).routes[0]; // Mapbox shape: routes[0].geometry is a GeoJSON line
    map.getSource('route').setData({ type: 'Feature', geometry: route.geometry, properties: {} });
    info.textContent = `${(route.distance / 1000).toFixed(2)} km, ${Math.round(route.duration / 60)} min`;
  } catch (err) { info.textContent = 'Error: ' + err.message; }
});
</script>
</body>
</html>

Verwendete APIs

  • Routing GET api.mapx.at/v1/directions/{profile}/{coordinates}