OpenLayersで緯度経度の線を地図に描画する

GPSロガーで記録した緯度経度をOpenLayersを使って表示するサンプルです。ここでは OpenLayers が持つ KML や GPX の読み込み機能は使わないで、配列で渡した緯度経度の値を使う方法を紹介しています

# 対象環境

* OpenLayers v5.3.0

# サンプル

こんな感じでコードを書けばいいと思います

```html:ol_sample.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>OL Sample - LineString</title>
    <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
    <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css">
  </head>
  <body>
    <div id="map" class="map"></div>
    <script>
      const Map = ol.Map;
      const View = ol.View;
      const Feature = ol.Feature;
      const Polyline = ol.format.Polyline;
      const Point = ol.geom.Point;
      const TileLayer = ol.layer.Tile;
      const VectorLayer = ol.layer.Vector;
      const OSM = ol.source.OSM;
      const VectorSource = ol.source.Vector;
      const Icon = ol.style.Icon;
      const Stroke = ol.style.Stroke;
      const Style = ol.style.Style;
      const Geom = ol.geom;

      const coordinates = [   // 経度、緯度の順で定義
                              [135.495650, 34.702113],
                              [139.767130, 35.680776]
                          ];

      var route = new Geom.LineString(coordinates);
      route.transform('EPSG:4326', 'EPSG:3857');  // 地理座標系(WGS84) の EPSG:4326 からメルカトル図法の EPSG:3857 に変換します

      const routeCoords = route.getCoordinates();
      const routeLength = routeCoords.length;

      const routeFeature = new Feature({
        type: 'route',
        geometry: route
      });
      const startMarker = new Feature({
        type: 'icon',
        geometry: new Point(routeCoords[0])
      });
      const endMarker = new Feature({
        type: 'icon',
        geometry: new Point(routeCoords[routeLength - 1])
      });

      const styles = {
        'route': new Style({
          stroke: new Stroke({
            width: 6, color: [237, 30, 164, 0.8]
          })
        }),
        'icon': new Style({
          image: new Icon({
            anchor: [0.5, 1],
            src: 'http://github.com/suzutsuki0220/TrackView/blob/master/src/image/caution.png?raw=true'  // 適当に置き換えてください
          })
        })
      };

      const vectorLayer = new VectorLayer({
        source: new VectorSource({
          features: [routeFeature, startMarker, endMarker]
        }),
        style: function(feature) {
          return styles[feature.get('type')];
        }
      });

      var map = new Map({
        target: document.getElementById('map'),
        view: new View({
          center: routeCoords[0],
          zoom: 7
        }),
        layers: [
          new TileLayer({
            source: new OSM()
          }),
          vectorLayer
        ]
      });
    </script>
  </body>
</html>
```

東京と大阪を結ぶ線が表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61404/c6056f74-deb0-c934-1b53-3e974370c5c0.png)

# クラスについて

View、SouceやFeatureなど多くの名前が出てくるので、まずそれらの役割をまとめました。OpenLayersに初めて触れた時に苦労する所だと思いました。

公式ドキュメントには https://openlayers.org/en/latest/doc/tutorials/concepts.html に書かれてます

| 名前 | 役割 | 補足 |
| --- | --- | --- |
| Map | 基底となるクラス | MapクラスにViewやLayerなどをセットします |
| View | 地図の表示に関する設定を保持します | サンプルでは中央位置とズームレベルを設定してます|
| Source | Layerを構成するためのデータを定義します | 地図のプロバイダーを変えたり、GeoJSONやKMLなどデータ形式を指定したりします |
| Layer | 画面の表示を構成するレイヤです `Tile` `Image` `Vector` `VectorTile` | サンプルでは次のレイヤを使ってます。`Tile: ` OSM地図の表示、 `Vector: ` coordinates(経度・緯度) の線の表示 |
| Feature | Layerを構成するための要素 |  |

`Polyline` , `Point` , `Icon` , `Stroke` , `Style` は大体分かると思うので省略します
`Geom` は Geometry です

# ぼやき

今まで Google MapのAPIを使っていたのですが、地図の劣化や料金値上げの話題が上がっているので、別の地図に切り替えようと思って OpenLayers を触ってみました。

OpenLayers で出来ることは [公式のExamples](https://openlayers.org/en/latest/examples/) にまとまっているのですが、経路を描画するドンピシャな例は見つからず、最も近そうな [Marker Animation](https://openlayers.org/en/latest/examples/feature-move-animation.html) では例が複雑すぎでした。Example の polyline を変えれば良いと思ったものの、経度緯度の配列に変えただけでは経路は表示されなくて苦労してました。雑なメモだと思いますが、お役に立てば幸いです