PR

ローカルHTMLファイルをクリックしてPCのTopoJSONデータをブラウザ表示

国土数値情報行政区域TopoJSON
この記事は約20分で読めます。

昔と違いセキュリティレベルが向上している現在では、ローカルに置かれたTopoJSONファイルやCSVファイルをJavascriptでフォームを使わずに読み込んでブラウザに表示させることは困難になってきています。

でもこれを回避するためにご使用されているパソコンにローカルでWebサーバを起動させることも簡単ではありません。

そこでPowerBI向けのTopoJSONファイルとは別に、TopoJSONデータが改行コードを含まない1つの大きなテキストデータになっている事を活用し、Javascriptのconst変数にTopoJSONデータを丸ごと代入する式にして外部Javascriptファイルとしてご提供する事にいたします。

  • なおサンプルコーディングではこのconst変数の名前は「mytopoJson」としています。詳細は後程ご説明いたします。

今回は、「Leaflet」と呼ばれるブラウザーに地図を表示するためのJavascriptライブラリを使って、上記の外部Javascriptファイルと同じローカルフォルダーの中にあるHTMLファイルをクリックするだけで地図情報を表示できるサンプルコーディングをご紹介いたします。

スポンサーリンク

ブラウザに地図データを表示するために必要なJavascriptライブラリ

Webブラウザに地図データを読み込んで表示させるためのJavascriptライブラリですが、「地図 javascript ライブラリ」でGoogle検索をするといろいろなライブラリが存在している事が解ります。

そのなかの「OpenLayers」では下記OpenLayersサイトのExamplesを見るとTopoJSON形式の地図データを直接読み込むことができそうです。

ただし今回使用する「Leaflet」では読み込める地図データはGeoJSON形式となり、そのためTopoJSON形式のデータを読み込むためには一度GeoJSON形式に変換をする必要があります。

このTopoJSON形式からGeoJSON形式への変換は、githubの中に作られているtopojsonのウェッブサイト「TopoJSON APIリファレンス」に書かれている「topojson.featue(topologyobject) 」というコマンドで実行することができます。

具体的な使い方は後の章でご説明いたします。

サンプルコーディングをご説明するにあたりお含み置きいただきたい考慮点

国土数値情報 各都道府県行政区域TopoJSONデータには属性情報として行政区域コードだけがセットされています。

属性情報(properties)としてTopoJSONデータにセットしている行政区域コードには「KEY」という名称を付けています。
そのためサンプルコーディングのなかにも「feature.properties.KEY」という形で記述されていますのでお含み置きいただければ幸いです。

行政区域コード以外の情報につきましては別ファイルに保存することでTopoJSONデータのファイルサイズを小さくすると共に、様々な情報を後の章でご説明する方法でデータ加工していただく事で、行政区域コード別の統計情報に基づき行政区域を色分けした分布図を作り、それに付随する情報を付加させて表示することができます。

その他にも使い方は色々とある事と存じますが、まずは上記の内容が簡単に実現できるような仕組みをご提供したいと考えます。

ただそうは言いましてもスタンドアロンで動くWebプログラミングをするうえでも、HTMLやCSSなどWebページを構成したり装飾したりするための知識は必要であるとともにプログラミング言語としてのJavascriptの知識は必要となります。

そうなりますとLeafletやTopoJSONにまつわるコーディング知識のところは、なるべく目に触れなくて済むように必要最小限だけ残して、その他のところは外部Javascriptファイルに移動させる建付けにしています。

従いまして最小限変更をしなければならない箇所だけHTMLファイルの中に残して、それ以外は外部Javscriptファイルに格納する形でサンプルコーディンクをしています。

必要があれば外部Javascriptファイルの内容も変更していただく事になりますが、そこの部分は今回のご説明の中には含まれていませんので予めお含み置きいただければ幸いです。

統計情報を地図に反映させるために必要な統計データの加工方法について

TopoJSONデータの属性情報には行政区域コードがセットされていますので、統計データは行政区域コードを検索キーの項目として使用する必要があります。

統計情報にはヘッダー項目があっても、なくても大丈夫です。
サンプルコーディングで統計情報を参照する際には配列の並び、具体的には「配列[0]は行政区域コード、配列[1]は郡・政令都市名、配列[2]は…」というように並び順を使って受け取りをしています。

ここでは統計データをExcelを用いて作成する事を前提にご説明をいたします。

なお国土数値情報 行政区域データに含まれている属性情報につきましては「国土数値情報 各都道府県行政区域TopoJSONデータのご紹介」に記載しておりますのでご参照いただければ幸いです。

Excelでの表作成とCSV UTF-8(コンマ区切り)(*.csv)ファイルとしての保存

左図でA列からC列の情報は北海道の国土数値情報 行政区域データからセット、D列とE列のデータはe-Statの「地域(都道府県、市区町村の主要データを表示)」から北海道を抽出してセットしています。なおヘッダー項目は下記の情報を表しています。

N03_007行政地域コード
N03_003郡・政令都市名
N03_004市区町村名
A1101総人口(人)
A161001未婚者割合(15歳以上人口)

  • 行政地域コードはゼロで始まる数字が使用されています。
    これをExcelにそのまま入力するとゼロが消えてしまうため、A列の表示形式は初めに「文字列」に設定してください。
  • e-Statの情報および国土数値情報 行政区域データとの結合方法につきましてはあらためまして別途ご説明いたします。

統計情報は上図のように先頭のA列に検索キーの項目である行政区域コードを設定した上で、その後続する列に地図上に表示させたい情報を並べた表形式で作成します。

表が完成しましたら、Excelのメニューバーから「ファイル」→「名前を付けて保存」→「このPC→(保存先のフォルダーを適宜選択します)」とクリックして行くと左図のようなウインドウが開きます。

ここで「ファイルの種類」を「CSV UTF-8(コンマ区切り)(*.csv)」にプルダウンメニューから選択し、ファイル名はここでは「01data.csv」にしています。

なおファイル名に付けた「01」は北海道の都道府県コードを使用しています。

  • ファイル名の入力が終わりましたら「保存」ボタンをクリックします。
  • CSVファイル形式を選択していますので、その後Excelが複数回確認警告メッセージを表示してきますが「保存をする」方の「OK」「はい」の選択肢を選んでください。

保存したCSVファイルをテキストエディタで外部Javascriptファイルに変更します。

冒頭でも記載しましたがCSVファイルをJavascriptでフォームを使わずに読み込んでブラウザに表示させることはできなくなってきています。

そこで保存したCSVファイルからテキストエディタを使って改行コードをすべてタブ(TAB)コードに置き換える事で、全体を一つの大きなレコードにしてJavascriptのconst変数に代入する形に編集します。
そして外部Javascriptファイルとして拡張子を「XXX.js」に変更した上で名前を付けて保存します。
なおサンプルコーディングでは「XXX」のところは「01data」にしています。

  • このconst変数の名前はサンプルコーディングのなかでは「mycsv」としています。詳細は後程ご説明いたします。
  • テキストエディタの操作につきましてはMicrosoftのVisual Studio Codeでのやり方をあらためまして別途ご説明いたします。なお文字コードはUTF-8のままで保存します。

実際のサンプルコーディンクのご説明

サンプルデータは北海道の地図情報を使用して下図のような形式でデータを表示しています。

なお赤枠線はご説明のために後から付加したものです。

Noエリア内容
ローカルファイルを表示
しています
コントロールボックス
ズームレベル表示
属性情報表示
凡例
帰属表示
ポップアップ表示
ズームアップ・ダウン
使用承認表示
縮尺

なお下記サンプルコーディンクのHTMLファイルで設定しているのは④、⑤、⑦と地図情報になり、それ以外は外部Javascriptファイルに外だししていますので、あらかじめお含み置きいただければ幸いです。

1~9行目/全78行

<!DOCTYPE html>
<html><head><meta charset='utf-8'>
<title>Hokkaido01</title>
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.css' />
<link rel='stylesheet' href='N03_19.css' />
<script src='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.min.js"></script>
</head>
<body><div id='myMap'></div>

上記はHTMLの中のheadタグとbodyタグの部分になります。

9行目にはbodyタグの終わりがありませんが、10行目からscriptタグが始まっていくつかscriptタグが続きます。その後にbodyタグとhtmlタグの終わりが来ます。

つまりこのサンプルコーディングのbody要素は9行目のdivタグだけというHTMLとしては特殊な作りになっています。
そしてこの1つのdivタグにいろいろな地図情報を表示させるのが「Leaflet」と呼ばれるブラウザーに地図を表示するためのJavascriptライブラリの機能・役割になります。

5行目にリンクしているcssファイルはサンプルコーディングのため作成したものでHTMLファイルと同じローカルフォルダに格納します。

それ以外の4行目、6~7行目で指定している「Leaflet,css」「Leaflet.js」「topojson.min.js」のファイルはインターネット上にある「CND(Content Delivery Network)のサイト」から読み込んでいます。

「CND」の説明につきましては下記JPNICのページをご参照ください。

また使用しているCNDのサイト「Cloudflare CDN」のパフォーマンス及び信頼性指標の情報につきましては下記のサイト(英語)をご参照ください。

10~31行目/全78行

<script>
//TopoJSONの中に書かれているobject名をセット
const g_jsonObjid = 'N03_19_01';
//Zoomに関するする変数
var g_inilatlng = [43.423,143.221];
var g_inizoomlvl = 8;
var g_minzoomlvl = 7;
var g_maxzoomlvl = 15;
//カラースケール(凡例)に関する変数
var g_grades = [0, 15, 18, 21, 24, 27, 30, 33];
var g_gradecolors = ['#F9EFEF', '#EDC0B4', '#ECB193', '#EEA96E', '#D0615D', '#B14D75', '#923E83','#602F72'];
var g_legendTitle = '<h4>未婚者割合<br>色スケール(%) </h4>';
//csvデータに関する変数
var g_arrdata = []; //csvデータを格納する二次元配列
var g_arrkey = []; //検索キー項目を格納する一次元配列
var g_idx; //検索キー項目のindexをセット
//復元コマンド
const g_cmd = 'nYzJrkyMsIDOzUDKyR3ciV3cu42bzp0bw9Gd512KpMDLwUDO0gic0NnY1NnLu92cK9GcvRXettSK0wyM4EjNoIHdzJWdz5ibvNnSvB3b0lXb';
</script>
<script type='text/javascript' src='01data.js' charset='utf-8'></script>
<script type='text/javascript' src='N03_19_01.js' charset='utf-8'></script>
<script src='N03_09.js' charset='utf-8'></script>

上記コーディングの中で「必要に応じて変更をしていただきたい箇所」及び「値が決まっていて変更はしないもの(行項目に#を表記)」を下記一覧表でご説明いたします。

変数名
ファイル名
No内容
12#g_jsonObjidTopoJSONファイルの中に明記されているオブジェクトID
14g_inilatlngHTMLファイルを開いた時の地図の画面中心座標を緯度、経度で
指定します。小数点以下は必要に応じて可変
15g_inizoomlvl③⑧HTMLファイルを開いた時のズームレベルを指定します。
16g_minzoomlvl最小ズームレベルを指定します。(0でも表示されます)
17g_maxzoomlvl最大ズームレベルを指定します。(国土地理院タイルは18まで)
19g_grades凡例に表示する数値のグレードを配列で小さい値から順番に設定します。
20g_gradecolorsグレードに設定する色を十六進の色コードで配列に指定します。
19行目の数値グレードと相対する形で設定します。
21g_legendTitle凡例のタイトルに表示する名称を指定します。
27#g_cmdTopoJSONファイルには欠損箇所を設定しています。
それをこのコンスタント情報を元に欠損箇所を復元します。
簡易な仕組みですのでインターネットで公開する形ではなく
パソコン上に置いて使用するのが前提となります。
2901data.js前の章でご説明しましたCSVデータを外部Javascriptファイルで
保存したファイルを指定します。
30#N03_19_01.jsTopoJSONデータを外部Javascriptファイルとしてご提供しているファイルを指定します。
31#N03_09.jsサンプルコーディングで外だしをした部分のコーディングが保存してあります。

28~63行目/全78行

<script>
g_arrdata = mysetCSVtoArray(mycsv); //csvデータ読み込み二次元配列にセット
//jsonデータ読み込みと地図描画
mydrawMap(myTopo2GeoJSON());
//LeafletオブジェクトでGeoJSONに変換された地図データを用いて描画
function mydrawMap(mygeoj) {
    g_leafletjson = L.geoJSON(mygeoj,{
        style: function (feature) {
            g_idx = g_arrkey.findIndex(function(i) {return i === feature.properties.KEY});if (g_idx == -1) return;
            return {
                color: '#EF7598',
                weight:  1.0,
                opacity: 0.3,
                fillColor: mycolorScale(Math.round(g_arrdata[g_idx][4])),
                fillOpacity: 0.4
            };
        },
        onEachFeature: function (feature, layer) {
            layer.on({ mouseover: highlightFeature, mouseout: resetHighlight });
        }
    }).bindPopup(function (layer) {
        g_idx = g_arrkey.findIndex(function(i) {return i === layer.feature.properties.KEY});if (g_idx == -1) return '<ul><li>NOT FOUND</li></ul>';
        var j1 = Number(g_arrdata[g_idx][4]);
        var j2 = Number(g_arrdata[g_idx][3]);
        return '<ul><li>'
            + g_arrdata[g_idx][1]
            + g_arrdata[g_idx][2]
            + '</li><li>未婚者割合:  ' + Math.round(j1) + '%'
            + '</li><li>総人口  :' + ('       ' + j2.toLocaleString()).slice(-7).replace(/ /g, ' ') + '人'
            + '</li></ul>';
    }).addTo(g_map);
}

いきなりプログラムらしくなってしまいましたが、最終的に地図情報をセットする箇所のご説明に入ります。

変数名
関数名など
No内容
33#mysetCSVtoArrayCSVデータを変数「mycsv」に代入したデータを読み込み
二次元配列「g_arrdata」にセットする関数になります。
35#mydrawMap37行目からの関数をここで呼んでいます。
myTopo2GeoJSON上記関数の引数にセットされている関数で、変数「mytopoJson」
にセットされたデータを読み込みJavascriptライブラリ
「topojson.min.js」を使用してGeoJSON形式に変換をする関数です。
38#L.geoJSONJavascriptライブラリ「leaflet.jp」を使ってGeoJSONレイアを
作り出す機能です。
39stylestyleは38行のgeoJSONのオプション設定で、各ポリゴンの
スタイルを指定します。
40#g_idxポリゴンの属性情報から行政区域コード(feature.properties.KEY)
を取得し、検索キー項目の配列(g_arrkey)のどこに格納されているか?
そのインデックスをセットします。
もしも見つからない場合はNOT FOUNDを返します。
42-46color-
fillopacity
ポリゴンの線の色、線の太さ、線の透過度、面の色、面の透過度
を設定します。
45g_arrdata[g_idx][4]二次元配列の添え字[4]はCSVデータの5番目の項目を示します。
もしも分布図に面の色で表したい項目を変更する時は添え字
の数を変更します。
54-55g_arrdata[g_idx][4]
g_arrdata[g_idx][3]
添え字[4]は45行目と同じで、[3]は総人口を示しています。
地図をクリックした時に表示されるポップアップに表示する
内容を変える時はこの添え字の数を変更します。
56-61文字列式ポップアップに表示する内容をHTMLタグ付きで1つの文字列で
指定します。ポップアップの見栄えを変更する時はHTMLタグ
のスタイルシートの設定を変更します。

64~78行目(最終行)

//未婚者割合分布表示設定
g_info.update = function (fp) {
    if (g_idx == -1) return this._div.innerHTML = '<h4>  未婚者割合分布  </h4>' + (fp ? 'NOT FOUND' : 'カーソル ON');
    var j1 = Number(g_arrdata[g_idx][4]);
    var j2 = Number(g_arrdata[g_idx][3]);
    this._div.innerHTML = '<h4>  未婚者割合分布  </h4>' +
        (fp ? '<pre><b>'
            + g_arrdata[g_idx][1]
            + g_arrdata[g_idx][2]
            + '</b><br>未婚者割合:   <b>' + Math.round(j1) + '%'
            + '</b></b><br>総人口  :<b>' + ('      ' + j2.toLocaleString()).slice(-7) + '人</b>'
        : 'カーソル ON');
}
g_info.addTo(g_map);
</script>
</body></html>

画面上右手のズームレベル表示の下の位置(No④)に、カーソルがあたっているポリゴンの属性情報を表示させる領域を設定しています。

67~75行目にかけては先ほどのポップアップの時と同じ属性情報を表示していますが違う内容にすることもできます。

地図上にカーソルがあたっていない時に「カーソルON」の表示をさせるために三項演算子が使われているために解り難くなっていますが表示させる情報はひとつの文字列として指定します。

実際に動かせるサンプルコーディングのご紹介

パソコンに保存したローカルHTMLファイルから起動するためのサンプルコーディンクになります。

今回zipファイルに収納しているTopoJSONデータはサンプル用に極端に座標値を簡素化したものであり、販売データとは異なるためデータに欠損箇所を設定しておりません。

そのためサンプルコーディングのなかの復元コマンドには値が設定してありませんので、あらかじめお含み置きいただければ幸いです。

下記リンクをクッリクしてzipファイルをダウンロードしていただき、適当な場所で解凍すると、上記でご説明したサンプルコーディングを動かすことがきます。

解凍してできる5つのファイルはすべて同じフォルダーに保存してください。
なお必要なJavascriptライブラリを読み込むためにインターネットにつながる環境で動かす必要があります。是非一度ご確認をいただければ幸いです。

なお恐れ入りますが動作確認をしたブラウザ環境は下記になります。
Edge以外はHTMLファイルをブラウザ上にドラック&ドロップすることで表示させることができます。

  • Google Chrome バージョン: 81.0.4044.138
  • Internet Explorer11 更新バージョン11.0.185(KB4550905)
    • 「このWebページはスクリプトやActivexコントロールを実行しないように制限されています。」というメッセージがブラウザ画面下部に表示された時はメッセージ右端の「ブロックされているコンテンツを許可」ボタンをクリックすると動きます。
  • Microsoft Edge  44.18.18362.449.0
    • 「ファイルを選択しマウス右ボタンでショートカットメニューを表示→プログラムから開く→Microsoft Edge」で確認しています。
  • FireFox 76.0.1

最後に

視覚的な分布図を作成するのであれば、PowerBIを使用した方が面倒臭いコーディングが無くて良い事と存じます。

PowerBIではなく今回のやり方を選択する場面としては、下記のようなケースではないはないか?と推察されます。

  • 情報共有する相手がPowerBIを導入していないので事前導入が必要なく共有可能なやり方を使いたい。
  • 地図情報を大きくして見たい。
  • PowerBIでは表現できない地図情報の加工が必要

あまりコーディングになじみがない場合には採用する理由として弱いかもしれません…

なお今回ご紹介したサンプルコーディングですがフォーマットを固定してしまうならば変数に値を設定するだけで動くようにすることも可能ですが…そうすると自由度がなくなってしまうところが悩ましいです。

次回はMicrosoftが提供するテキストエディタ「Visual Studio Code」を使用した統計情報の具体的な加工の仕方についてご説明致します。

以上最後までご一読いただき誠にありがとうございました。