使用 OpenLayers 从 GraphHpper 绘制路线

Use OpenLayers for Draw Route from GraphHpper

我刚开始使用地图 GraphHopper、OpenStreetMap 和其他库。我想绘制由 GraphHopper 路由引擎生成的路由(实际上是 Java 语言)。是否可以使用 OpenLayer 从 GH 绘制路线?
我读过这个GWT-OpenLayer, but I can't find how to write a route in real road like this GraphHopper Routing Example
我希望 openlayers API 可以满足我的需求

  1. GH 路由引擎生成从 A(经度、纬度)到 B(经度、纬度)的路径
  2. OpenLayers GWT 从 GH 绘制每条路线

任何帮助将不胜感激:)

GraphHopper 路由 API 与许多其他路由 API 非常相似,它可以直接从 JavaScript 应用程序(例如 OpenLayers)中获取,结果包含一条折线,如下所示本例中使用 https://openlayers.org/en/main/examples/feature-move-animation.html(但折线可以包含高程并具有标准的 ie5 比例因子)。更改 OpenLayers 示例以使用 GraphHopper 示例中的路由(我复制了 API 密钥,但对于生产,您应该拥有自己的密钥)结果是:

<!doctype html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css" type="text/css">
    <style>
      html, body, .map {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
      }
      #map {
        position: relative;
      }
      #controls {
        z-index: 1;
        position: absolute;
        bottom: 0;
        left: 0;
     }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
  </head>
  <body>
    <div id="map" class="map">
      <div id="controls">
        <label for="speed">
          speed:&nbsp;
          <input id="speed" type="range" min="10" max="999" step="10" value="60">
        </label>
        <button id="start-animation">Start Animation</button>
      </div>
    </div>
    <script type="text/javascript">

const center = [-5639523.95, -3501274.52];
const map = new ol.Map({
  target: document.getElementById('map'),
  view: new ol.View({
    center: center,
    zoom: 10,
    minZoom: 2,
    maxZoom: 19,
  }),
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM(),
    }),
  ],
});

// The polyline string is read from a JSON similiar to those returned
// by directions APIs such as Openrouteservice and Mapbox.

const api_key = 'ab642f98-3b45-4643-981d-9b80f58239a3';
const startLonLat = [111.352111, 0.136299];
const endLonLat = [111.299744, -0.255431];

fetch('https://graphhopper.com/api/1/route' +
  '?point=' + startLonLat.slice().reverse().join(',') +
  '&point=' + endLonLat.slice().reverse().join(',') +
  '&type=json&locale=en-US&key=' + api_key +
  '&elevation=true&profile=car'
).then(function (response) {
  response.json().then(function (result) {

    const polyline = result.paths[0].points;

    const route = new ol.format.Polyline({
      factor: 1e5,
      geometryLayout: 'XYZ'
    }).readGeometry(polyline, {
      dataProjection: 'EPSG:4326',
      featureProjection: 'EPSG:3857',
    });

    map.getView().fit(route);

    const routeFeature = new ol.Feature({
      type: 'route',
      geometry: route,
    });
    const geoMarker = new ol.Feature({
      type: 'geoMarker',
      geometry: new ol.geom.Point(route.getCoordinateAt(0)),
    });
    const startMarker = new ol.Feature({
      type: 'icon',
      geometry: new ol.geom.Point(route.getCoordinateAt(0)),
    });
    const endMarker = new ol.Feature({
      type: 'icon',
      geometry: new ol.geom.Point(route.getCoordinateAt(1)),
    });

    const styles = {
      'route': new ol.style.Style({
        stroke: new ol.style.Stroke({
          width: 6,
          color: [237, 212, 0, 0.8],
        }),
      }),
      'icon': new ol.style.Style({
        image: new ol.style.Icon({
          anchor: [0.5, 1],
          src: 'https://openlayers.org/en/main/examples/data/icon.png',
        }),
      }),
      'geoMarker': new ol.style.Style({
        image: new ol.style.Circle({
          radius: 7,
          fill: new ol.style.Fill({color: 'black'}),
          stroke: new ol.style.Stroke({
            color: 'white',
            width: 2,
          }),
        }),
      }),
    };

    let animating = false;

    const vectorLayer = new ol.layer.Vector({
      source: new ol.source.Vector({
        features: [routeFeature, geoMarker, startMarker, endMarker],
      }),
      style: function (feature) {
        // hide geoMarker if animation is active
        if (animating && feature.get('type') === 'geoMarker') {
          return null;
        }
        return styles[feature.get('type')];
      },
    });

    map.addLayer(vectorLayer);

    let speed, startTime;
    const speedInput = document.getElementById('speed');
    const startButton = document.getElementById('start-animation');

    function moveFeature(event) {
      const vectorContext = ol.render.getVectorContext(event);
      const frameState = event.frameState;

      if (animating) {
        const elapsedTime = frameState.time - startTime;
        const distance = (speed * elapsedTime) / 1e6;

        if (distance >= 1) {
          stopAnimation(true);
          return;
        }

        const currentPoint = new ol.geom.Point(route.getCoordinateAt(distance));
        const feature = new ol.Feature(currentPoint);
        vectorContext.drawFeature(feature, styles.geoMarker);
      }
      // tell OpenLayers to continue the postrender animation
      map.render();
    }

    function startAnimation() {
      if (animating) {
        stopAnimation(false);
      } else {
        animating = true;
        startTime = new Date().getTime();
        speed = speedInput.value;
        startButton.textContent = 'Cancel Animation';
        // hide geoMarker
        geoMarker.changed();
        // just in case you pan somewhere else
        map.getView().fit(route);
        vectorLayer.on('postrender', moveFeature);
        map.render();
      }
    }

    function stopAnimation(ended) {
      animating = false;
      startButton.textContent = 'Start Animation';

      // if animation cancelled set the marker at the beginning
      const coord = route.getCoordinateAt(ended ? 1 : 0);
      geoMarker.getGeometry().setCoordinates(coord);
      // remove listener
      vectorLayer.un('postrender', moveFeature);
    }

    startButton.addEventListener('click', startAnimation, false);
  });
});

    </script>
  </body>
</html>