ViteでビルドしたOpenLayersで地理院地図を表示する

フロントエンドビルドツールの[Vite](https://vitejs.dev/)を使用してビルドした[OpenLayers](https://openlayers.org/)で[国土地理院地図](https://maps.gsi.go.jp/development/ichiran.html)を表示します。

[Vite](https://vitejs.dev/)は高速で起動、更新ができるJavaScriptビルドツールで
TypeScriptやVue.js/React等のライブラリが設定なしですぐに使えます。
ホットリロードに標準対応しているので、ファイルを変更すると自動的にブラウザをリロードしてくれて開発が非常に楽です。

[OpenLayers](https://openlayers.org/)のバージョンは`v6.12.0`を使用します。

※gitとnode ver.12以上のインストールは省略。

## プロジェクトとViteのセットアップ

ViteでOpenLayersの公式HPの[チュートリアル](https://openlayers.org/en/latest/doc/tutorials/bundle.html)にある方法で可能。

プロジェクト用に新しい空のディレクトリを作成し、そのディレクトリに移動して以下のコマンドを実行する。
[create-ol-app](https://github.com/openlayers/create-ol-app)

```
npx create-ol-app {アプリケーションの名前}
```

`{アプリケーションの名前}`のディレクトリが作成されて
`ol`パッケージのインストールが正常に終了すれば完了。

## OpenLayersを実行して地図を表示

Git Bashやコマンドプロンプトで
以下のコマンドで作成された`{アプリケーションの名前}`のディレクトリへ移動し
開発サーバを起動します。

```
cd {アプリケーションの名前}
npm start
```

`npm start`を実行すると以下のようなログが表示されるので、
`> Local:{url}`に表示されるアドレスをブラウザで開きます。

```
$ npm start

> `{アプリケーションの名前}`@1.0.0 start
> vite


  vite v2.6.7 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 568ms.

```

ブラウザで開くと以下のような[OpenStreetMap(OSM)](https://www.openstreetmap.org/#map=5/35.0/135.0)を使用した世界地図がデフォルトで表示されます。

![osm.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584743/334ee102-e274-8f8e-1818-f3228e204fb5.png)


## 地理院地図を表示

`{アプリケーションの名前}フォルダ`以下に`main.js`というファイルが作成されているので、
こちらをエディタで開きます。

```javascript:main.js
import './style.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM()
    })
  ],
  view: new View({
    center: [0, 0],
    zoom: 2
  })
});
```

地図データはデフォルトで[OSM](https://www.openstreetmap.org/#map=5/35.0/135.0)が使用されています。
こちらを地理院地図を使用するよう変更したソースが以下です。

```javascript:main.js
import './style.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import {fromLonLat} from 'ol/proj';

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new XYZ({
        url: 'https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png'
      })
    })
  ],
  view: new View({
    center: new fromLonLat([139.7663672, 35.6806526]),
    zoom: 14
  })
});
```

ブラウザを確認すると地理院地図と東京駅が表示されているはずです。

## 出典

地理院地図は出典を明記する必要があるので`attribution`も追加しました。
画面サイズが狭いと折りたたみ表示されます。

```javascript:main.js
import './style.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import {fromLonLat} from 'ol/proj';
import {Attribution, defaults as defaultControls} from 'ol/control';

const attribution = new Attribution({
  collapsible: false,
});

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new XYZ({
        url: 'https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
        attributions: '<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">© 国土地理院</a>',  
      })
    })
  ],
  controls: defaultControls({attribution: false}).extend([attribution]),
  view: new View({
    center: new fromLonLat([139.7663672, 35.6806526]),
    zoom: 14
  })
});

function checkSize() {
  const small = map.getSize()[0] < 600;
  attribution.setCollapsible(small);
  attribution.setCollapsed(small);
}

window.addEventListener('resize', checkSize);
checkSize();
```