日本の旅客鉄道の変遷をMapbox GL JSで表示してみました


はじめに

国土数値情報の鉄道時系列データを用いて、日本の旅客鉄道の変遷(1950~2020年)をMapbox GL JS(v2)のタイムスライダー機能で表示してみました。

★★★↓高速道路バージョンはこちらの記事を参照願います。★★★
高速道路整備の変遷をMapbox GL JSで表示してみました

アウトプットイメージ

※「鉄道時系列データ」(国土交通省)
(https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N05-v1_3.html) を用いて作成

前提条件

  • 鉄道時系列データは令和2年の「N05-20_RailroadSection2.geojson」を用いています※。
  • ※ただし、フィルタで使用する、geojsonファイルの属性(設置期間(設置開始)(N05_005b)と設置期間(設置終了)(N05_005e))が文字列のため、あらかじめQGIS等で整数に変換したものを用いています。
  • 下記のコードでMapboxのアクセストークン、styleのURL及びN06-20_HighwaySection.geojsonのパスを入力してください。
  • なお、フィルタにはN05-20_RailroadSection2.geojsonの属性の「設置期間(設置開始)(N05_005b)」と「設置期間(設置終了)(N05_005e)」を用いています。
  • また、ラベル(鉄道路線の名称)にはN05-20_RailroadSection2.geojsonの属性の「路線名(N05_002)」を用いています。

html、CSS、JavaScript

Railway_transition.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>日本の鉄道路線の変遷</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.4.1/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.4.1/mapbox-gl.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
        }
    </style>
</head>

<body>
    <style>
        .map-overlay {
            font: 18px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
            position: absolute;
            width: 25%;
            top: 0;
            left: 0;
            padding: 10px;
        }

        .map-overlay .map-overlay-inner {
            background-color: #fff;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            border-radius: 3px;
            padding: 10px;
            margin-bottom: 10px;
        }

        .map-overlay h2 {
            line-height: 24px;
            display: block;
            margin: 0 0 10px;
        }

        .map-overlay .legend .bar {
            height: 10px;
            width: 100%;
            background: linear-gradient(to right, #00008b, #00ffff);
        }

        .map-overlay input {
            background-color: transparent;
            display: inline-block;
            width: 100%;
            position: relative;
            margin: 0;
            cursor: ew-resize;
        }
    </style>

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

    <div class="map-overlay top">
        <div class="map-overlay-inner">
            <h1>日本の旅客鉄道の変遷</h1>
            使用データ:<br>
            <a href="https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N05-v1_3.html" target="_blank" rel="noopener">
                国土数値情報, 鉄道時系列データ(国土交通省)</a><br><br>
            <label id="year_label"></label>
            <input id="slider" type="range" min="1950" max="2020" step="1" value="1950">
        </div>
        <div class="map-overlay-inner">
            <div id="legend" class="legend">
                <div class="bar"></div>
                <div align="center">昔(1950年)← → 最近(2020年)</div>
            </div>
        </div>
    </div>

    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>

    <script>
        mapboxgl.accessToken = 'Mapboxのアクセストークンを入力してください';
        const map = new mapboxgl.Map({
            container: 'map',
            style: 'styleのURLを入力してください', // 例)mapbox://styles/mapbox/satellite-v9
            center: [139.7527995, 35.685175],
            zoom: 8
        });

        // ズーム・回転
        map.addControl(new mapboxgl.NavigationControl());

        // フルスクリーンモードのオンオフ
        map.addControl(new mapboxgl.FullscreenControl());

        // スケール表示
        map.addControl(new mapboxgl.ScaleControl({
            maxWidth: 200,
            unit: 'metric'
        }));

        function filterBy(year) {
            const filters = ['all', ['<=', 'N05_005b_int', year], ['>=', 'N05_005e_int', year]];
            map.setFilter('railway-lines', filters);
            map.setFilter('railway-labels', filters);

            // スライダー表示用ラベル
            document.getElementById('year_label').textContent = year.toString() + '';
        }

        map.on('load', () => {
            // jsonCallback(highway);
            d3.json(
                'N05-20_RailroadSection2.geojsonのパスを入力してください',  // 例)data/N05-20_RailroadSection2.geojson
                jsonCallback
            );
        });

        function jsonCallback(data) {
            map.addSource('railway', {
                'type': 'geojson',
                'data': data
            });

            // ライン
            map.addLayer({
                'id': 'railway-lines',
                'type': 'line',
                'source': 'railway',
                'layout': {
                    'line-join': 'round',
                    'line-cap': 'round'
                },
                'paint': {
                    'line-color': [
                        'interpolate',
                        ['linear'],
                        ['get', 'N05_005b_int'],
                        1950,
                        '#00008b',
                        2020,
                        '#00ffff'
                    ],
                    'line-width': 5,
                    'line-opacity': 0.7
                }
            });

            // ラベル(鉄道路線の名称)
            map.addLayer({
                'id': 'railway-labels',
                'type': 'symbol',
                'source': 'railway',
                'layout': {
                    'text-field': ['concat', ['to-string', ['get', 'N05_002']]],
                    'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
                    'text-size': 12
                },
                'paint': {
                    'text-color': 'rgba(0,0,0,0.5)'
                }
            });

            // フィルター実行
            filterBy(1950); // 初期表示
            document.getElementById('slider').addEventListener('input', (e) => {
                const year = parseInt(e.target.value, 10); // スライダーで選択した年次を整数化
                filterBy(year);
            });
        }
    </script>

</body>

</html>

参考文献