はじめに
- 1kmメッシュ滞在人口(全国人流オープンデータ)をMapbox GL JSで表示してみました。
- Mapbox GL JSの表示部分は、こちらのブログ記事を参考にさせていただきました。
- 国土交通省が2019年・2020年を対象に、全国の「1kmメッシュ別の滞在人口データ」を全国人流オープンデータとして公開していますので、今回はこちらのデータを用いています。
- Mapboxのアクセストークンが必要になります。
アウトプットイメージ
※出典:「全国の人流オープンデータ」(国土交通省) https://www.geospatial.jp/ckan/dataset/mlit-1km-fromto ※上記出典とは別に、編集・加工等を行ったこちらのブログ記事(https://t.co/eR52JTnmaO)を参考にさせていただきながら、1kmメッシュ滞在人口(全国人流オープンデータ)をMapboxGLJSで表示してみた😀
— shi_works⛅ (@syanseto) August 1, 2021
出典:「全国の人流オープンデータ」(国土交通省)
※2020年8月平日昼https://t.co/xrimNC92Gs#Mapbox pic.twitter.com/WmfL7Sq87L
前提条件
- 1kmメッシュ滞在人口(全国人流オープンデータ)は、csv形式のデータで提供されていますが、Mapbox GL JSで表示するために、予めQGIS等でgeojson形式のデータ(メッシュポリゴンデータ)に変換しています。
- 1kmメッシュ滞在人口(全国人流オープンデータ)のcsv形式のデータは以下のとおりです。
- オープンデータ(人流データ)の定義書はこちらを参照してください。
- 変換後のgeojson形式のデータは以下のとおりです。
html、css
mesh1km_pop.html
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>1kmメッシュ滞在人口</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js'></script>
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://d3js.org/d3-request.v1.min.js"></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
.legend {
background-color: #fff;
border-radius: 3px;
bottom: 30px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10);
font: 15px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
padding: 10px;
position: absolute;
right: 10px;
z-index: 1;
line-height: 25px;
height: 280px;
}
.legend h4 {
margin: 0 0 10px;
}
.legend div span {
border-radius: 50%;
display: inline-block;
height: 15px;
margin-right: 10px;
width: 15px;
color: orangered
}
</style>
</head>
<body>
<!-- Load the `mapbox-gl-geocoder` plugin. -->
<script
src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.7.2/mapbox-gl-geocoder.min.js"></script>
<link rel="stylesheet"
href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.7.2/mapbox-gl-geocoder.css"
type="text/css">
<div id="tooltip"></div>
<div id='map'></div>
<div id='county-legend' class='legend'>
<h4>1kmメッシュ滞在人口</h4>
<div><span style='background-color: rgb(44, 123, 182)'></span>0 - 4,000</div>
<div><span style='background-color: rgb(100, 165, 205)'></span>4,000 - 8,000</div>
<div><span style='background-color: rgb(157, 207, 228)'></span>8,000 - 12,000</div>
<div><span style='background-color: rgb(199, 230, 219)'></span>12,000 - 16,000</div>
<div><span style='background-color: rgb(237, 247, 201)'></span>16,000 - 20,000</div>
<div><span style='background-color: rgb(255, 237, 170)'></span>20,000 - 24,000</div>
<div><span style='background-color: rgb(254, 201, 128)'></span>24,000 - 28,000</div>
<div><span style='background-color: rgb(249, 158, 89)'></span>28,000 - 32,000</div>
<div><span style='background-color: rgb(232, 91, 58)'></span>32,000 - 36,000</div>
<div><span style='background-color: rgb(215, 25, 28)'></span>36,000 - 40,000</div>
</div>
</body>
<script type="text/javascript" src=script.js></script>
</html>
JavaScript
script.js
mapboxgl.accessToken = "Mapboxのアクセストークンを入力してください";
// Mapbox Streets読み込み
const map = new mapboxgl.Map({
container: "map",
style: 'mapbox://styles/mapbox/streets-v9',
center: [139.7527995, 35.685175],
zoom: 12
});
// Create a popup, but don't add it to the map yet.
let popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});
let hoveredStateId = null;
map.on("mousemove", "2DmeshLayer", function (e) {
map.getCanvas().style.cursor = 'pointer';
if (e.features.length > 0) {
if (hoveredStateId) {
map.setFeatureState({ source: 'meshdata', id: hoveredStateId }, { hover: false });
}
hoveredStateId = e.features[0].layer.id;
map.setFeatureState({ source: 'meshdata', id: hoveredStateId }, { hover: true });
}
popup.setLngLat(e.lngLat)
.setHTML(
"<div><b>3次メッシュコード </b>" + e.features[0].properties.meshid + "</div>" +
"<div><b>1kmメッシュ滞在人口</b></div>" +
"<div>" + Math.round(e.features[0].properties.population) + " 人</div>")
.addTo(map);
});
// When the mouse leaves the state-fill layer, update the feature state of the
// previously hovered feature.
map.on("mouseleave", "2DmeshLayer", function () {
map.getCanvas().style.cursor = '';
popup.remove();
if (hoveredStateId) {
map.setFeatureState({ source: 'meshdata', id: hoveredStateId }, { hover: false });
}
hoveredStateId = null;
});
let POP_1 = ["<", ["get", "population"], 4000];
let POP_2 = ["all", [">=", ["get", "population"], 4000], ["<", ["get", "population"], 8000]];
let POP_3 = ["all", [">=", ["get", "population"], 8000], ["<", ["get", "population"], 12000]];
let POP_4 = ["all", [">=", ["get", "population"], 12000], ["<", ["get", "population"], 16000]];
let POP_5 = ["all", [">=", ["get", "population"], 16000], ["<", ["get", "population"], 20000]];
let POP_6 = ["all", [">=", ["get", "population"], 20000], ["<", ["get", "population"], 24000]];
let POP_7 = ["all", [">=", ["get", "population"], 24000], ["<", ["get", "population"], 28000]];
let POP_8 = ["all", [">=", ["get", "population"], 28000], ["<", ["get", "population"], 32000]];
let POP_9 = ["all", [">=", ["get", "population"], 32000], ["<", ["get", "population"], 36000]];
let POP_10 = ["all", [">=", ["get", "population"], 36000], ["<", ["get", "population"], 40000]];
let colors = [
'rgb(44, 123, 182)',
'rgb(100, 165, 205)',
'rgb(157, 207, 228)',
'rgb(199, 230, 219)',
'rgb(237, 247, 201)',
'rgb(255, 237, 170)',
'rgb(254, 201, 128)',
'rgb(249, 158, 89)',
'rgb(232, 91, 58)',
'rgb(215, 25, 28)'
]
const meshToMap = (meshdata) => {
map.addSource('meshdata', {
type: 'geojson',
data: meshdata,
});
map.addLayer({
'id': '2DmeshLayer',
'type': 'fill',
'source': 'meshdata',
'layout': {},
'paint': {
"fill-color":
["case",
POP_1, colors[0],
POP_2, colors[1],
POP_3, colors[2],
POP_4, colors[3],
POP_5, colors[4],
POP_6, colors[5],
POP_7, colors[6],
POP_8, colors[7],
POP_9, colors[8],
POP_10, colors[9],
colors[9]
],
"fill-outline-color": "white",
"fill-opacity": ["case",
["boolean", ["feature-state", "hover"], false],
1,
0.5
]
}
});
};
let meshGeoJsonURL = 'data/monthly_mdp_mesh1km_202008_1_0.geojson';
const handleGetData = (err, meshdata) => {
meshToMap(meshdata);
}
d3.queue()
.defer(d3.json, meshGeoJsonURL)
.await(handleGetData);
// コントロール関係表示
var nav = new mapboxgl.NavigationControl();
map.addControl(nav, 'top-left');
// スケール表示
map.addControl(new mapboxgl.ScaleControl({
maxWidth: 200,
unit: 'metric'
}));
// Add the control to the map.
map.addControl(
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
mapboxgl: mapboxgl
})
);
参考文献