自転車シェアリングのオープンデータをLeafletで可視化してみる

# オープンデータ

[自転車シェアリングのオープンデータ](https://urbandata-challenge.jp/idc/data-bikeshare)をWebページで可視化する．[OpenStreet株式会社](https://www.openstreet.co.jp/)が運営する自転車シェアリングのサービス「[HELLO CYCLING](https://www.hellocycling.jp/)」で利用されるステーションや自転車の情報が提供されている．ステーションのデータは，次のJSON形式で与えられる（GBFS: General Bikeshare Feed Specification）．`lat`は緯度，`lon`は経度，`name`はステーション名，`address`は住所である．

```json
{
    "lat":35.15174,
    "lon":136.91396,
    "name":"ライブリー鶴舞",
    "address":"愛知県名古屋市昭和区鶴舞2丁目14-4-1",
    "station_id":"7405",
    "rental_uris": 
    {
        "ios":"https://www.hellocycling.jp/app/port/detail/7405?referrer=odpt",
        "web":"https://www.hellocycling.jp/app/port/detail/7405?referrer=odpt",
        "android":"https://www.hellocycling.jp/app/port/detail/7405?referrer=odpt"
    },
    "parking_hoop":false,
    "parking_type":"street_parking",
    "contact_phone":"+8105038218282",
    "is_charging_station":false,
    "vehicle_type_capacity":
    {
        "num_bikes_now":0,
        "num_bikes_limit":3,
        "num_bikes_parkable":3,
        "num_bikes_rentalable":0
    }
}
```

# 開発環境

開発環境として[CodePen](https://codepen.io/)を利用する．CodePenはオンラインでHTML，CSS，JavaScriptを利用したWebページ（**Pen**と呼ばれる）の開発が可能である．アカウントがないとPenの保存ができないため，事前にアカウントを取得すること．

ここでは次のライブラリを利用する．

- オンライン地図のライブラリ [Leaflet](https://leafletjs.com/)
- コーディングを支援するライブラリ [jQuery](https://jquery.com/)

Penを新規作成し，`Settings -> JS`でライブラリをCDN(Content Delivery Network)で導入する．

[![Image from Gyazo](https://i.gyazo.com/417e21959c132324ea9f59363d060349.png)](https://gyazo.com/417e21959c132324ea9f59363d060349)

同様にLeafletのCSSを`Settings -> CSS`から追加する．

`https://unpkg.com/leaflet@1.9.3/dist/leaflet.css`

[![Image from Gyazo](https://i.gyazo.com/d52ea5ecdb3ba1dc405493a55c92b19c.png)](https://gyazo.com/d52ea5ecdb3ba1dc405493a55c92b19c)

# ソースコード

## HTML

`div`要素を作成する．`id`属性には`map`を設定する．

```html
<div id="map"></div>
```

### CSS

地図を全画面表示するための設定を記述する．`html`要素と`body`要素の高さを`100%`に設定する．`id`属性が`map`の高さを`100%`に設定する．

```css
html, body{
  height: 100%;
}

#map{
  height: 100%;
}
```

## JavaScript

`$.getJSON()`で自転車シェアリングのオープンデータを読み込む．住所が`愛知県`で始まるレコードのみをフィルタし，`station_list`に追加する．`station`の緯度（`lat`），経度（`lon`），ステーション名（`name`）を利用して，マーカー（`L.marker`）を生成して表示する．

```javascript
const tile = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
const attribution = "&copy; <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors";
const station_url = "https://mukai-lab.info/classes/graduation_preperation_1/station_information.json";

let lat = 35.1706431 ; // 緯度
let lon = 136.8816945; // 経度
let zoom = 14; // ズームレベル

// 地図
let map = L.map("map");

// 緯度・経度・ズームレベルの設定
map.setView([lat, lon], zoom);

// タイルを地図に追加
L.tileLayer(tile, 
  {
    attribution: attribution
  }
).addTo(map);

// ステーションのデータ
let station_list = [];

// 対象の住所
let target_address = "愛知県"

// JSONファイルの読込
$.getJSON(station_url, (data) => {

  // 対象の住所のステーションのデータを取得
  for(let station of data["data"]["stations"]){
    let address = station["address"];
    if(address.startsWith(target_address)){
      station_list.push(station);
      console.log(station); // ログの出力
    }
  }
  
  // ステーションをマーカーとして表示
  for(let station of station_list){
    let lat = station["lat"];
    let lon = station["lon"];
    let name = station["name"];
    
    let marker = L.marker([lat, lon]);
    marker.bindPopup(`<p>${name}</p>`)
    marker.addTo(map);
  }
  
});
```

# デモ

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="XWYyqqX" data-user="nmukai" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/nmukai/pen/XWYyqqX">
  ShareCycleMap</a> by Naoto Mukai (<a href="https://codepen.io/nmukai">@nmukai</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>