MapLibreとは
MapLibreは、高性能でカスタマイズ可能な地図描画を可能にするオープンソースライブラリです。OpenStreetMapが地理データを提供する基盤として働き、MapLibreがそのデータを表示および操作するためのツールとなりますMapbox GL JSのオープンソース版として誕生し、現在も多くの開発者によって支持されています。
この記事で作るもの
この記事では地図のウェブアプリを作成します。地図上のピン情報はkintoneのアプリ(ウェブデータベース)で管理され、kintone上で情報を追加、編集、削除することでウェブアプリに変更を反映することが出来ます。
HTTPリクエストとkintoneのREST APIを使うことにより、外部からkintoneアプリ内とのデータの送受信が出来ます。今回の記事ではnode.jsで地図のウェブアプリを作りますが、フロントエンドから直接kintoneのような外部サービスにHTTPリクエストを投げるとCORSエラーで失敗します。ExpressとViteで立てた中継サーバを立てることにより、kintoneへの情報のリクエスト、及びkintoneからのデータのレスポンスを可能にします。
kintoneでピン情報を管理する利点
ピン情報をkintone上で管理する利点はいくつかあります
- 直接地図のコードをいじらなくても、kintoneのGUI上で情報の更新が可能になることで、エンジニアじゃない現場の担当者でも地図のメンテが可能になる
- kintoneアプリにワークフローを設定することで、承認されたピン情報しか表示出来ないように設定出来る
- ピン情報を更新した際に、kintoneアプリに変更履歴が自動的に残る
- コード上からピン情報のデータを削減することにより、コードの可読性を上げることが出来る
他にも利点は色々とありますが、さっそく地図連携アプリ作っていきたいと思います。
地図連携アプリの作り方
kintoneのアプリを作成し、データを手動で入れ、APIトークンを発行します。GitHubからnode.jsのプロジェクトをクローンし、適切なパラメータをコードに反映してからウェブアプリを起動させ、APIトークン認証でkintoneアプリでデータの送受信をします。これから手順を案内します。
kintoneアプリの準備
まずはkintone側の準備から説明します。
kintone環境の準備する
kintoneの環境が無い方は、開発者サイトから1年間無償で使用できる『開発者ライセンス』という名のkintone環境を取得出来ます。下記のサイトで『開発者ライセンスを申し込む』をクリックし、フォームに必要事項を入力して下さい。申込後、メールでkintone環境の情報が送られてきます。所要時間はおおよそ10分程度です。
kintoneアプリを作成する
kintoneで作るウェブデータベースは『アプリ』と呼ばれています。
まず、地図のピン情報を溜めるためのkintoneアプリを作成します。場所の名前、住所や緯度経度など、地図のピンに必要な情報をイメージしながら作りましょう。
この記事で作成するアプリに必要なフィールドは下記のデーブルに記載したので、参考してください。フィールドを配置したら、一つ一つ設定を変更することが出来るので、表示名、フィールドコードやオプションなどを変更します。ちなみに表示名はUI上でユーザに見えるフィールドの名前で、フィールドコードはフィールドのユニークな識別子になります。フィールドコードは外部からHTTPリクエストをする際に重要な設定となります。
フィールドタイプ | 表示名 | フィールドコード | その他の設定 |
---|---|---|---|
文字列(1行) | タイトル | title | |
文字列(1行) | 住所 | address | |
ラジオボタン | 種類 | type | 選択肢に 『レストラン』『観光地』『ショッピング』『ビジネス』 を追加する |
数値 | 緯度 | lat | |
数値 | 経度 | lon |
フィールドの配置や設定が終わったら、右上の青いボタンからアプリを公開します。
kintoneアプリにレコードを追加する
ウェブデータベースを作成出来ましたが、データがまだ入っていません。適当に手動でいくつかデータ(レコード)を追加しましょう。
kintoneアプリからAPIトークンを発行する
他のシステムと連携をするために、kintoneアプリから認証用のトークンを発行します。アプリの設定画面からAPIトークンを生成します。「レコード閲覧」のアクセス権にチェックを入れます。APIトークンを手元でメモした後に、アプリを更新します(⚠注: アプリを更新しないとAPIトークンは使用出来ません)。
これでkintoneアプリの準備が出来ました。
node.jsプロジェクトの作成
次に、ウェブアプリの基本となるnode.jsのプロジェクトを作成します。
この記事では下記のGitHubプロジェクトを使います。
フロントエンドの実装
まずはローカルのパソコンのターミナル/コンソールを開き、レポジトリをクローンします。
git clone https://github.com/kintone-workshops/maplibre-kintone.git
maplibre-kintoneディレクトリに移動し、必要なパッケージをインストールします。
cd maplibre-kintone npm install
kintoneの設定情報を保管している.env.example
ファイルを.env
という名前でコピーします。このファイルは後ほど中身を変更します。
cp .env.example .env
フロントエンドのスクリプトを走らせます。
npm run dev
ブラウザでhttp://localhost:5173/
にアクセスすると地図が表示されるはずです。
地図は表示されるのですが、ピンは立っていません。この記事ではkintoneアプリで管理された情報をピンとして地図に表示させたいので、kintoneアプリとのやりとりが実装出来るようにサーバを立てます。ウェブアプリのフロントエンドのスクリプトはこのサーバにアクセスし、サーバがkintoneアプリにHTTPリクエストを投げて、必要な情報をサーバ経由でフロントエンドに返してくれます。
.envファイルの更新
まず、サーバがアクセスするkintone環境の情報を設定する必要があります。プロジェクト内の.env
ファイルをテキストエディタなどで開きましょう(通常非表示のファイルではあるので、見えるように設定をしましょう)。下記のような仮の環境情報が入っています。
SUBDOMAIN = "MY_SUBDOMAIN" APPID = "APP_ID" APITOKEN = "MY_API_TOKEN_WITH_GET_PERMISSIONS"
SUBDOMAINとAPPIDのパラメータは、ブラウザで開いているkintoneアプリのURLを確認して変更します。APITOKENはこの記事で発行したAPIトークンを使用します。
必要な情報を.env
ファイルに登録し、保存します。例として、下記のようになりますが、kintone環境ごとにこの情報は変わるので、自分の環境に合うパラメータを入れて下さい。
SUBDOMAIN = "cy-hwg" APPID = "66" APITOKEN = "k009FDpo474FGk40irgDFgfdg04irggdASDF4k"
バックエンドの実装
今開いているターミナルはそのままにして、新しいターミナルを開きましょう。プロジェクトの中のbackend
ディレクトリに移動し、必要なパッケージをインストールします。
cd backend npm install
server.jsファイルを走らせることでExpressとViteを使ってバクエンドサーバを立ち上げます。
node server.js
これで現在フロントエンドのスクリプトとバックエンドのスクリプトが同時に走ってる状態になります。
localhost:5173
にアクセスしてるブラウザを更新しましょう。kintoneアプリに登録された情報がピンとして地図に表示されるはずです。
kintoneデータを取得するコードの解説
このプロジェクトではフロントエンドからバックエンドにリクエストを投げ、バックエンドからkintoneのREST APIを叩くことによって、kintoneアプリとのデータの送受信を可能にしています。
まずはバックエンドから見ると、/backend/server.js
でこのような記述が見られます
app.get('/getData', cors(corsOptions), async (req, res) => { const fetchOptions = { method: 'GET', headers: { 'X-Cybozu-API-Token': apiToken } } const response = await fetch(multipleRecordsEndpoint, fetchOptions); const jsonResponse = await response.json(); res.json(jsonResponse); });
この最初の一行が『ルーティング』という手法を使っていて、『もしここのエンドポイント向けにGETリクエストが来たら、ここの関数内の処理を実行する』という内容になっています。このGETリクエストは、後述するフロントエンドのスクリプトから来ます。
app.get('/getData', cors(corsOptions), async (req, res) => {
残りのコードはkintoneのREST APIの実行をfetchメソッドで実行しています。kintoneアプリから複数のレコードを取得するREST APIを、ドキュメントを参考にしながら設定しています。
const fetchOptions = { method: 'GET', headers: { 'X-Cybozu-API-Token': apiToken } } const response = await fetch(multipleRecordsEndpoint, fetchOptions); const jsonResponse = await response.json(); res.json(jsonResponse); });
フロントエンド側を確認すると /apiRequests/getRecords.js
で/getData
というエンドポイント向けに(厳密にいうと、サーバが立てられているlocalhost:5000の/getData
のエンドポイント向けに)fetchリクエストがされるコードが実装されています。
getRecords.js const getRecordsEndpoint = 'http://localhost:5000/getData'; export default async function getRecords() { const response = await fetch(getRecordsEndpoint); const jsonResponse = await response.json(); return jsonResponse; };
このコードが実際に呼ばれているのはmain.js
の方です
const kintoneData = await getRecords()
このように、フロントエンドのスクリプトからバックエンドの特定のエンドポイントにリクエストを投げています。リクエストを受け取ったバックエンドはkintoneとのデータの送受信をし、そのデータをフロントエンドに返しています。フロントエンドから直接外部サービスと通信するとCORSエラーというセキュリティ上の問題に当たるため、バックエンドからリクエストを投げるような仕組みの実装が必要になります。
地図連携アプリのの改変
この記事のプロジェクトをもとに、ぜひ自分好みの地図を作ってみてください。
kintoneアプリはいつでも設定画面からフィールドの変更が出来ます。用途に合わせて蓄積したいデータをイメージしながらフィールドを更新していきましょう。今回のAPIトークンにはレコード閲覧用の権限しか付与しませんでしたが、レコード追加用の権限などを追加することにより、ウェブアプリ側からkintoneアプリへのデータ追加も可能になります。
また、地図のタイルのスタイルを変更することにより、地図の表現を大きく変更することが出来ます。例えばこちらのタイルのスタイルをダウンロードし、プロジェクトに配置するとします。
https://github.com/K-Sakanoshita/community_mapmaker/blob/main/tiles/osmfj.json
main.js
のstyle
でこちらのファイルを読み込むように変更してみましょう。
const map = new maplibregl.Map({ container: 'map', // container id style: './osmfj.json', // style URL center: [139.767, 35.681], zoom: 3, maxBounds: bounds });
ウェブアプリの地図が3D表示されるようになりました!
用途に合わせて、好みの地図ウェブアプリを作ってみましょう!
終わりに
今回使用してるタイルサーバは無料で使えますが、個人か小規模の利用に抑えて下さい(詳しくはOpenStreetMapsの利用規約を参照ください)。もし大きなプロジェクトで使用することがありましたら、MIERUNEなどのタイル地図サービスを提供してる会社とご相談をお願いします。