Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MapLibreで地図サイトをつくる!

K.Sakanoshita
May 18, 2024
500

 MapLibreで地図サイトをつくる!

2024/05/19 ATC(TEQS)のワークショップ資料

K.Sakanoshita

May 18, 2024
Tweet

More Decks by K.Sakanoshita

Transcript

  1. P.2 自己紹介 - 坂ノ下 勝幸 ◼ 主な所属コミュニティ・団体 ⚫ OpenStreetMap Foundation

    Japan 理事 ⚫ Code for OSAKA 理事/Code for Harima,Kusatsu ⚫ 淀川アートネット ⚫ 諸国・浪漫 / etc.. ◼ 主な活動内容 ⚫ マッピングパーティの開催および協力 ⚫ ウィキペディアタウンの開催および協力 ⚫ オープンソース/データの活用(アプリ開発など) ◼ 目指していること ⚫ 地元の情報は、自分たちで発信する文化を作る ⚫ 現場こそ最強のツールとデータが使えるように P.2
  2. P.6 ワークショップの流れ ◼ 環境構築を始めよう ⚫ Visual Studio CodeとGitのインストール(無い方) ◼ 簡単な地図アプリをつくろう

    ⚫ 地図を表示するコードを入力 ⚫ ピンの表示するコードを入力 ◼ アプリをカスタマイズしよう ⚫ GitHubからforkし、手元の環境にClone ⚫ 設定ファイルを編集してマップをカスタマイズ ◼ 成果発表 ⚫ 各自で開発したアプリの発表 P.6
  3. P.8 環境構築 ◼ Gitのインストール ⚫ https://gitforwindows.org/ ⚫ インストール後、以下のコマンドを実行しておく ✓ git

    config --global user.email “自分のメールアドレス” ✓ git config --global user.name “自分の名前(GitHub上)" ◼ テキストエディタ ⚫ 推奨はVisual Studio Code(Git、簡易Webサーバも動くため) ◼ Webブラウザ ⚫ Google Chromeが一般的だがFirefoxでの動作確認も重要です ⚫ 両ブラウザは、CSSの初期値やフォントが少し異なるようで 片方の初期値に依存しないよう両方での確認が必要です P.8
  4. P.10 地図アプリの仕組み P.10 Webブラウザ(Chrome/Firefoxなど) あなたが作るアプリ タイルサーバー (地図配信) 各社のCDN (ライブラリ配布) MapLibre

    GL JS ・地図を表示するためのライブラリ Bootstrap ・画面のスタイルを整えるライブラリ その他 ・多言語対応、jQueryなどのライブラリ
  5. P.12 1.まずは地図表示 ◼ 以下のプログラムを入力しよう(ちょっと長いけど) P.12 <html> <head> <title>サンプル</title> <link rel="stylesheet"

    href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" /> <script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script> </head> <body> <div id="map" style="height: 100%;width: 100%;"></div> <script> var map = new maplibregl.Map({ container: 'map', style: 'https://k-sakanoshita.github.io/community_mapmaker/tiles/osmfj.json', // スタイル center: [135.4110, 34.6381], // 座標 zoom: 16, // ズームレベル pitch: 30 // 傾き }); </script> </body> </html>
  6. P.13 1.まずは地図表示の簡単な解説 ◼ 地図を表示させるだけなら簡単 P.13 <html> <head> <title>サンプル</title> <link rel="stylesheet"

    href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" /> <script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script> </head> <body> <div id="map" style="height: 100%;width: 100%;"></div> <script> var map = new maplibregl.Map({ container: 'map', style: 'https://k-sakanoshita.github.io/community_mapmaker/tiles/osmfj.json', // スタイル center: [135.4110, 34.6381], // 座標 zoom: 16, // ズームレベル pitch: 30 // 傾き }); </script> </body> </html> MapLibreを読み込む 地図を表示させる 画面表示サイズを指定
  7. P.14 注意すること ◼ 以下のスタイルの指示に沿って地図を表示する ◼ 上記のスタイルについて ⚫ 一般社団法人OpenStreetMap Foundation Japanが無償提供している

    地図配信サーバーを利用しています。あまり負荷を与えなければ 誰でも許可を得ず利用しても構わないので、ご利用ください ✓ 使う時は、上記のosmfj.jsonをダウンロードしてから使うようお願いします 今回はファイルのダウンロードが手間なので直接書いています ◼ 地図配信サーバについて ⚫ 世界で一番使われているのは恐らくGoogle Mapsかと思われますが、 MapBox社、MapTiler社など、各種企業が地図配信サーバーを提供 しているので、ビジネスなどで本格的に利用を始める時は、自分に あった地図配信サーバーを提供している会社と契約してください P.14 style: ‘https://k-sakanoshita.github.io/community_mapmaker/tiles/osmfj.json’
  8. P.15 2.地図にマーカーを追加してみよう ◼ 赤枠の箇所を追加入力してみよう P.15 <html> <head>(head部分は変更無し)</head> <body> <div id="map"

    style="height: 100%;width: 100%;"></div> <script> var map = new maplibregl.Map({ container: 'map', style: 'https://k-sakanoshita.github.io/community_mapmaker/tiles/osmfj.json', // スタイル center: [135.4110, 34.6381], // 座標 zoom: 16, // ズームレベル pitch: 30 // 傾き }); // マーカーの作成 var marker = new maplibregl.Marker() .setLngLat([135.4110, 34.6381]) .addTo(map) </script> </body> </html> マーカーの追加処理 緯度経度を指定して追加
  9. P.16 3.マーカーにポップアップを追加しよう ◼ 赤枠の箇所を追加入力してみよう P.16 <body> <div id="map" style="height: 100%;width:

    100%;"></div> <script> var map = new maplibregl.Map({ (map部分の処理は変更無し) }); // ポップアップの設定 var popup = new maplibregl.Popup({ offset: 25, // ポップアップの位置 closeButton: false, // 閉じるボタンの表示 }).setText('こんにちは') // マーカーの作成 var marker = new maplibregl.Marker() .setLngLat([135.4110, 34.6381]) .setPopup(popup) .addTo(map) </script> </body> ポップアップの追加処理 ポップアップ内容の設定
  10. P.18 4.マーカーアイコンを変えてみよう② ◼ 赤枠の箇所を追加入力してみよう P.18 <script> var map = new

    maplibregl.Map({ (map部分の処理は変更無し) }); // アイコンの設定 var icon = document.createElement(‘div’); icon.innerHTML = “<img src='train.png' style='width: 32px'>"; // ポップアップの設定 var popup = new maplibregl.Popup({ offset: 25, // ポップアップの位置 closeButton: false, // 閉じるボタンの表示 }).setText('こんにちは'); // マーカーの作成 var marker = new maplibregl.Marker({ element: icon }) .setLngLat([135.4110, 34.6381]) .setPopup(popup) .addTo(map) </script> アイコン画像の指定 アイコン画像をHTMLで指定
  11. P.21 5.駅のアイコンを追加してみよう③ ◼ 「data.js」を開き、一行目に「var datas =」を書きます P.21 var datas =

    { "type": "FeatureCollection", "generator": "overpass-turbo", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", "timestamp": "2024-05-18T17:08:16Z", "features": [ { "type": "Feature", "properties": { "@id": "node/346493769", "light_rail": "yes", "name": "中ふ頭", "name:en": "Nakafuto", 一行だけ先頭行に追加する
  12. P.22 5.駅のアイコンを追加してみよう④ ◼ Index.htmlに書いたアイコン設定~マーカー作成の部分を 「sub.js」ファイルに移動させ、以下のように編集しよう P.22 // アイコンを作る function makeIcon(data)

    { // アイコンの設定 var icon = document.createElement('div'); icon.innerHTML = "<img src=‘train.png' style='width: 32px'>"; // ポップアップの設定 var popup = new maplibregl.Popup({ offset: 25, // ポップアップの位置 closeButton: false, // 閉じるボタンの表示 }).setText(data.properties.name); // マーカーの作成 var marker = new maplibregl.Marker({ element: icon }) .setLngLat(data.geometry.coordinates) .setPopup(popup) .addTo(map) } 3つの処理を関数化する data内のnameを表示 data内の緯度経度を指定
  13. P.23 ◼ 「sub.js」の後、index.htmlを以下のように書き換えよう ちゃんと駅のマーカーが表示されるかな? <script> var map = new maplibregl.Map({

    (map部分の処理は変更無し) }); datas.features.forEach(data => makeIcon(data)) </script> 5.駅のアイコンを追加してみよう⑤ P.23 datasを一件ずつ取得してmakeIcon処理を呼び出す
  14. P.25 サンプルアプリ ◼ Community Mapmaker ⚫ https://github.com/K-Sakanoshita/community_mapmaker ⚫ ご自身のリポジトリにforkしてPCにCloneしてください ⚫

    Visual Studio CodeのLive Serverなどで実行させてください ◼ サンプルアプリの概要 ⚫ OpenStreetMapのデータベースをリアルタイムで取得した上で 指定したデータに絞り込んでアイコン表示を行う汎用アプリ ⚫ Google Spreadsheetと連携して、OpenStreetMapの施設情報と 別に用意したデータ(イベント情報や写真など)と 組み合わせて地図上に表示する機能もある ◼ 活用例 ⚫ 十三アートフェスマップ、大阪思い出残しマップ ⚫ 遊具のある公園マップなど P.25
  15. P.26 サンプルアプリの構成 ◼ ライブラリ ⚫ maplibre-gl 今回の主役1 ⚫ jquery Bootstrap4が必要なので残っています

    ⚫ Bootstrap4 Web画面のCSSフレームワーク ⚫ Osmtogeojson Overpass APIで取得したデータの変換 P.26
  16. P.27 サンプルアプリの構成 ◼ サンプルアプリ ⚫ dataフォルダ ✓ config-user.jsonc アプリの設定が書かれたファイル ✓

    category-ja.json OpenStreetMapのタグから種類名を判別するファイル ✓ marker.json OpenStreetMapのタグからアイコンを判別するファイル ✓ overpass-custom.json Overpass APIを呼び出す命令が書かれたファイル ✓ style.json MapLibreで地図を表示するためのスタイルファイル ⚫ libフォルダ ✓ Basiclib.js 汎用的な処理を書いたライブラリ ✓ winlib.js 画面操作などちょっとしたライブラリ ✓ geolib.js MapLibre操作などちょっとしたライブラリ ✓ poilib.js 地図に表示するマーカーを管理 ✓ overpasslib.js 今回の主役2「Overpass API」を操作 ⚫ cmapmaker.js アプリの本体プログラム ⚫ initialize.js アプリの初期化プログラム P.27 その他 Image:画像 maki-icon:アイコン
  17. P.29 地図を表示するスタイル ◼ MapLibreは様々なタイルサーバに対応している ⚫ 今回はラスタタイルとベクタタイルの設定方法を説明する ✓ ラスタタイル:256px * 256px

    の地図画像(要するにドット絵) ✓ ベクタタイル:3D演算して都度描画する画像 ⚫ 地図の表示は「new maplibregl.Map(パラメータ)」で出来る ✓ 実行結果を map 変数などに入れておく(マーカー追加などで利用する) ⚫ 地図表示のスタイルは tilesフォルダ内のosmfj.json で指定 地図表示のカスタマイズは手間なので 扱いに慣れてきたら調べてみよう P.29 【geolib.js】地図表示エリアの設定(init内) this.map = new maplibregl.Map({ "container": 'mapid', "style": this.styles[this.selectStyle], "maxZoom": Conf.maxZoom, "zoom": Conf.initZoom, "antialias": true, "hash": true, "center": Conf.initView });
  18. P.30 スタイルファイルの概要説明 ◼ スタイルファイルはsourceとlayersエリアの設定が大事 ⚫ タイルサーバーを提供している会社は、このファイルを作るための スタイル編集ツール(マウス操作で楽々設定)を提供している ラスタタイル設定はconfig-system.jsonの「OSM_Standard」参照 P.30 {

    “style”: { “version”: 8, // 8固定 “sources”: { “ソース名”: { // ソース名は自分で決めて良い url: “タイルサーバのurl”, “type”: “vector” // ベクタタイルサーバは”vector” } }, “layers”: { { 背景の設定 }, // レイヤー設定がいろいろ { 土地利用の設定 } } }
  19. P.32 OpenStreetMapのデータについて ◼ OpenStreetMapのデータは「ODbL」と呼ばれるライセンス ⚫ 基本的には「@OpenStreetMap Contributors」の著作権帰属表示を する以外は自由に使えます(商用利用も含めて好きに出来る) ⚫ データベースからデータを一部抜き出した場合もODbLが適用され

    ますが、その「データを使って地図などの派生物を作った場合」は 制作著作物となり、作者が自由にライセンスを付けることが出来る ⚫ 例えば、OpenStreetMapのデータをもとに地図画像を作った場合、 作った人がライセンスを決められる(コピー不可とするのも可能) ✓ Tシャツなどのグッズ、作曲・歌詞の元ネタ、アート作品なども同様 ✓ データと作品を分けて扱えるので、商用利用時の自由度が高まっている ✓ 参考) https://qiita.com/nyampire/items/b0cbdd142d76bcc66d9c P.32
  20. P.34 Overpass API ◼ OSM地図データから個別に選択された部分を取り出すAPI ⚫ Web APIによる地理空間データベースとして提供されている ⚫ 読み取り専用だが、ユーザー認証が不要なので気軽に使える

    ◼ OpenStreetMap公式のOverpass APIは提供されていない ⚫ ドイツやフランス、ロシアの企業や団体が個別に提供されている ⚫ OSM WikiにOverpass API提供サーバーの一覧がある ✓ https://wiki.openstreetmap.org/wiki/Overpass_API ⚫ 日本国内でテスト運用しているサーバーもある ✓ https://overpass.openstreetmap.jp/ ⚫ いずれも無料で使えるが、常識の範囲内での利用が良い ✓ ドイツのサーバはよく使われる半公式な存在だが、短時間で何度も APIを叩くと、1分ほどアクセスを拒否されるなど制約もある P.34
  21. P.35 Overpass QL ◼ Overpass APIはWeb APIで公開されている ◼ サーバAPIアドレス以降に下記のパラメータを指定する ⚫

    ?data=[out:json][timeout:30][bbox:Area];(Query);out body meta;>;out skel;`; ⚫ Area 緯度経度 (例) [bbox: 34.75,135.32,34.77,135.35] ⚫ Query検索条件(例) node["leisure"="park"]; 上記のQuery言語のことをOverpass QLと呼ぶ P.35 ノード(点)の公園を探す 北西の緯度経度と 南東の緯度経度で 四角い範囲を返す // overpass.js より let LL = mapl.getLL(), query = ""; let maparea = LL.SE.lat + ',' + LL.NW.lng + ',' + LL.NW.lat + ',' + LL.SE.lng; overpass.forEach(val => query += val + ";"); let url = Conf.OverPassServer + `?data=[out:json][timeout:30] [bbox:${maparea}];(${query});out body meta;>;out skel;`; console.log("OverPassControl: getGeojson: " + url);
  22. P.36 Overpass Turboで遊んでみよう ◼ Overpass QLを触れる以下のサイトを開こう ⚫ https://overpass-turbo.eu/ ◼ 大阪市へ移動し、「ウィザード」ボタンを押す

    ◼ 「toilets in osaka」と入力し、クエリを作成して実行を押す P.36 toilets in osaka 「クエリを作成して実行」を押す
  23. P.37 Overpass QL ◼ Overpass QLは様々な機能が用意されている詳しくはWiki ⚫ https://wiki.openstreetmap.org/wiki/JA:Overpass_API/Overpass_QL ⚫ Chat

    GPT便利。例「大阪市内の図書館を出すOverpass QLを教えて」 ◼ 基本的なクエリの書き方 ⚫ node or way or relation[key=value] ✓ node : 点 ✓ way : 線・エリア ✓ relation : 組み合わせ ✓ key=value : OSMのタグ(key=value形式) ⚫ OSMのタグは下記参照 ✓ https://wiki.openstreetmap.org/wiki/JA:Map_Features ✓ 世界中のあらゆる動かないものをマッピング出来るよう日々見直し中 P.37 地図は、点、線、エリアの 組み合わせで作られている
  24. P.38 サンプルアプリの設定 ◼ dataフォルダ内のoverpass-custom.jsonを参照 初期設定では、店舗と工房を表示するよう設定している P.38 { "osm": { "stores":

    { "overpass": [ "nwr[¥"shop¥"]", "nwr[¥"craft¥"]" ], "tags": [ "shop", "craft" ], "expression": { "stroke": "#c0c0c0", "stroke-width": 1 }, "titles": [ "name", "operator" ] } } } OpenStreetMapのタグがshop or craftを検索 nwrは点と線とエリア全てを意味する 上記で検索した結果から指定した タグのデータだけを絞り込む設定 取得した施設や店舗がエリアの 場合、枠を指定した色で塗る
  25. P.40 (再掲)サンプルアプリの構成 ◼ サンプルアプリ ⚫ dataフォルダ ✓ config-user.jsonc アプリの設定が書かれたファイル ✓

    category-ja.json OpenStreetMapのタグから種類名を判別するファイル ✓ marker.json OpenStreetMapのタグからアイコンを判別するファイル ✓ overpass-custom.json Overpass APIを呼び出す命令が書かれたファイル ✓ style.json MapLibreで地図を表示するためのスタイルファイル ⚫ libフォルダ ✓ Basiclib.js 汎用的な処理を書いたライブラリ ✓ winlib.js 画面操作などちょっとしたライブラリ ✓ geolib.js MapLibre操作などちょっとしたライブラリ ✓ poilib.js 地図に表示するマーカーを管理 ✓ overpasslib.js 今回の主役2「Overpass API」を操作 ⚫ cmapmaker.js アプリの本体プログラム ⚫ initialize.js アプリの初期化プログラム P.40 その他 Image:画像 maki-icon:アイコン
  26. P.41 サンプルアプリの構成 ◼ サンプルアプリの構成は以下のイメージ P.41 initialize.js ライブラリの読み込み 設定ファイルの読み込み 地図初期化、イベント登録 cmapmaker.js

    地図画面上にあるボタンや マーカーから呼び出される winlib.js geolib.js poilib.js overpasslib.js listllib.jsなど cmapmaker.jsから必要に応じて呼び出される maplibre-gl MapLibreはmaplib.js/経由で間接的に呼び出す タイルサーバ Overpassサーバ
  27. P.43 何を開発するか考える ◼ しばらくサンプルアプリを遊んでみよう ⚫ 不便な所、機能を追加したい所を考えてみよう ⚫ 遊具以外に表示したい地物(アイコン)を考えてみよう ◼ 表示したいアイコンを思いついた方

    ⚫ 以下のサイトを開き、OSMタグを調べてみよう ⚫ https://wiki.openstreetmap.org/wiki/JA:Map_Features ✓ 例えばトイレは 「amenity=toilets」でマッピング ✓ 消火器、自動販売機、ベンチ、ゴミ箱などもあります ✓ 好きな組み合わせもOK。どんなマップを作りますか? P.43
  28. P.45 まずはサイトタイトルの変更 ◼ サイトタイトルを変更 ⚫ index.htmlのタイトルタグを変更しよう ◼ 説明文の見直し ⚫ config.jsonのaboutTitle~licenceMessageを変更しよう

    ✓ メニューやタイトルをクリックした時のメッセージが変化します ✓ cmapmaker.jsのviewMessageで表示させているので確認してみよう ◼ メニューの追加、変更 ⚫ config.jsonのmenuを参考に、メニューを変更して見よう ⚫ メニュー表示は「画面左上」と「詳細表示の画面左上」がある ✓ 画面左上は“menu“、 「詳細表示の画面左上」は”detailMenu”で変更できる P.45
  29. P.46 表示させる地物の変更 ◼ 表示させる地物を変更する ⚫ ./data/overpass.json のタグを見直そう ✓ 複数のタグを書いた場合、「and」では無く「or」でクエリは計算される ⚫

    tags内の書式は「overpassから取得したデータの絞り込み用」 ✓ 例えば、「amenity」で取得すると本当に様々なデータが取得される ✓ この場合、tagsで「amenity=toiltes」と書けばトイレだけ絞り込みが出来る ⚫ expressionの書式はラインの描画用 ✓ 敷地(way or relation)の場合、自動的に ラインを書くので、その描画色を指定する ※塗りつぶしは行いません P.46 "tags": [ "leisure=park", "leisure=playground", "landuse=recreation_ground", "playground" ], "expression": { "stroke": "#409040", "stroke-width": 2 }
  30. P.47 マップコントロールの追加 ◼ MapLibreには任意のコントロールを追加出来る ⚫ 以下のコードをinitialize.jsに追加するとhelloが左上に表示される 入力画面や表示エリアを追加して、もっと 分かりやすいアプリを目指してみるのも良い P.47 //

    basehtmlに代入したHTMLを画面の左上に追加するサンプル mapLibre.addControl( “top-left”, // 表示位置 bottom-right:右下 “baselist”, // 配置したDOMのIDを指定する “<div>hello</div>”, // 追加したいHTML “mapLibre-control m-0 p-0“ // 配置したDOMのCSSを指定する );
  31. P.49 他にも機能や設定があります ◼ 処理中を示すアニメーション制御 ◼ config-user.json で設定可能な項目 ◼ その他 ⚫

    アイコンのファイル名は ./data/marker.json で指定 ⚫ 「公園」などの種別名は ./data/category-ja.json で指定 P.49 winCont.spinner(true); // falseにすると消える "splashUrl": "./image/Playgrounds.png", “initZoom”: 14, // 初期ズーム(大きいほどズームする) “maxZoom”: 21, // 最大ズーム(21だと一軒家レベル) “viewCenter”: [ // 初期表示の緯度経度 135.4828, 34.7212 ], “PoiZoom”: “stores”: 13, // アイコンを表示し始めるズーム
  32. P.53 参考情報 ◼ OSM Wiki(Overpass API/QL) ⚫ https://wiki.openstreetmap.org/wiki/Overpass_API ⚫ https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL

    ◼ Overpass関連の説明記事 ⚫ https://qiita.com/K-Sakanoshita/items/0c610d76bba2e7245ea5 ⚫ https://qiita.com/Aruneko/items/ef2e7efb4925a2f8515f ◼ MapLibre(Official Site) ⚫ https://maplibre.org/maplibre-gl-js/docs/API/ ⚫ MapLibreで使えるベクタタイルサーバ(OSMFJ提供) ✓ https://wiki.openstreetmap.org/wiki/Japan/OSMFJ_Tileserver P.53
  33. P.54 参考情報(続き) ◼ OpenStreetMap ⚫ 世界がOpenStreetMapを必要とする理由 https://qiita.com/nyampire/items/073c850f083cf9fb8d35 ⚫ learn OSM(はじめてからのOpenStreetMapガイド)

    https://learnosm.org/ja/ ◼ 講師(坂ノ下)のサイト ⚫ GitHub K-Sakanoshita https://github.com/K-Sakanoshita ✓ OpenStreetMapを駆使したWebアプリを公開中 ⚫ まち歩きマップメーカー(自由に加工&使える地図画像を作る) https://armd-02.github.io/mapmaker/ ⚫ コミュニティマップメーカー https://github.com/K-Sakanoshita/community_mapmaker P.54