2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PleasanterとLeafletを組み合わせた地図機能を導入する

Posted at

はじめに

Pleasanterの利用例として住所録や顧客リストとして利用されている事例も多いかと思います。そのような場合、Pleasanterの画面上で地図を表示させたいケースもあるのではないでしょうか。
この記事では、PleasanterとLeafletと組み合わせて、Pleasanterに格納された位置情報をもとに対象地点を地図上に表示させる例をご紹介します。

以下の画像が最終的な実現例です。

Leafletとは

Leafletは、オープンソースのJavaScript地図ライブラリで、軽量でありながら様々な地図機能を備えています。Leafletについては、公式サイトや QiitaのLefletに関する投稿を確認してください。

サンプルデータ

地図に表示するサンプルデータとして、東京都のオープンデータカタログサイトで公開されている中野区の医療機関データを利用しました。

今回は予め対象となる地点の緯度と経度が記載されたデータを利用しています。
所有しているデータが住所情報のみの場合はジオコーディングサービスを利用するなどして、緯度、経度の情報を別途用意してください。

事前の準備

Pleasanterの動作環境

Pleasanterのセットアップについては割愛します。
今回のデモではPleasanterのバージョンは ver.1.3.47.0 を使用しています。

プリザンターのインストール | Pleasanter

サンプルデータのインポート

前述のサンプルデータをPleasanterへインポートします。 利用したデータは医療施設のデータであるため、所在地情報のほか、診療科目など様々な情報が記載されていますが、今回のデモでは最低限、施設の名称と緯度、経度の情報があれば実現できます。

PleasanterでのCSVインポートの操作方法については以下のマニュアルに記載されています。

テーブル機能:レコードのインポート | Pleasanter

ヘッダーにHTMLを挿入

対象サイトのテーブルの管理から HTMLを選択し、以下のコードを 挿入位置 Head bottomを指定します。出力先は 編集一覧 を指定します。

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>

今回、Leafletのkライブラリは CDNに配置されたものを参照しています。

Download - Leaflet - a JavaScript library for interactive maps

Pleasanter の ver.1.3.45.0 でリリースされた 「HTMLヘッダ及びBODYのスクリプトの位置に任意のHTMLを出力する機能を追加」という機能を使うことで、上記のように任意のHTMLコードを埋め込みができるようになりました。

Pleasanter テーブルの管理:HTML | Pleasanter

編集画面へ地図を埋め込む

まずは、取り込んだ複数の医療施設データのうち、一施設のみを表示させた編集画面に地図を埋め込んだ表示をさせてみます。

スタイルの設定

対象サイトのテーブルの管理からスタイルを選択し、以下のコードを貼り付けます。出力先は 編集 を指定します。

#mapid {
   width:calc(100% - 20px);
   height:300px;
   margin:10px;
}

地図を埋め込む領域のサイズを指定します。

スクリプト

対象サイトのテーブルの管理からスクリプトを選択し、以下のコードを貼り付けます。出力先は 編集 を指定します。緯度、経度の格納先の項目名は適宜変更してください。

$p.events.on_editor_load = function () {

    // 画面内の コメント欄の前に openstreetmap の地図を挿入する
    const mapDiv = document.createElement('div');
    mapDiv.id = 'mapid';
    $("#CommentField").before(mapDiv);

    //Zoomレベルを指定
    let zoom = 15;
    // 画面内の緯度lat ,経度 lng を読み取り、地図
    let lat = parseFloat($p.getControl('ClassF').val());
    let lng = parseFloat($p.getControl('ClassG').val());
    let map = L.map('mapid').setView([lat, lng], zoom);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);
    L.marker([lat, lng]).addTo(map);
}

$p.events.on_editor_load は編集画面を読み込んだときに実行されます。
サンプルでは 分類F(ClassF)と分類G(ClassG)にそれぞれ緯度、経度を格納しており、この値をもとに地図にマーカーを設定します。

開発者向け機能:スクリプト:$p.events.on_editor_load | Pleasanter
Documentation - Leaflet - a JavaScript library for interactive maps

Leafletの地図の操作に関するは、Leafletのクイックスタートガイドやリファレンスを参照してください。

Quick Start Guide - Leaflet - a JavaScript library for interactive maps
Documentation - Leaflet - a JavaScript library for interactiv

編集画面への地図埋め込み動作例

ここまでの設定を行い、編集画面を開くと以下のようにコメント欄の上部に地図が表示されます。
edit-2.png

一覧画面への地図埋め込み

続いて一覧画面に表示された複数の施設を同様に地図に表示させてみます。

一覧表の項目にセルCSSを設定

テーブルの管理から一覧を選択、対象となる列の詳細設定で以下の例ようにセルCSSを指定します。設定するセルCSS名はどのような値でも構いません。

項目の名称 設定するセルCSS名
名前 cell_name
所在地 cell_address
緯度 cell_lat
経度 cell_lng

セルCSSをは一覧画面で表示される表の項目列(th要素やtd要素)毎にCSSクラス名を指定することができます。主な目的はスタイル(CSS)と組み合わせたセルの装飾ですが、ここで項目列毎にクラスを設定することで、スクリプトから列名を指定しての値の参照が容易になります。

テーブルの管理:一覧画面:項目の詳細設定:セルCSS | Pleasanter

スタイルの設定

対象サイトのテーブルの管理からスタイルを選択し、以下のコードを貼り付けます。出力先は 一覧 を指定します。

#MainForm {
    width:70%;
}
#mapid {
   position:fixed;
   top:0px;
   right:0px;
   width:calc(30% - 20px);
   height: calc(100% - 140px);
   margin: 50px 10px 10px 10px;
}

通常は画面幅いっぱい表示される一覧表を幅70%に制限し、残りの30%に地図を埋め込む領域を作成しています。

スクリプトの設定

対象サイトのテーブルの管理からスクリプトを選択し、以下のコードを貼り付けます。出力先は 一覧 を指定します。

// マーカーを格納するための変数
var markers = L.featureGroup();
var map;

//地図を表示するエリアを作成し、地図を初期化
function initializeMap() {

    // 画面内の MainForm の後に地図を挿入
    const mapDiv = document.createElement('div');
    mapDiv.id = 'mapid';
    $("#MainForm").after(mapDiv);

    // Leaflet.jsで地図オブジェクトを生成
    map = L.map('mapid');

    // OpenStreetMapのタイルレイヤーを設定
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 
    {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);
}

//一覧 table 内の各行のデータを取得し、マーカーを地図へ追加
function addMarkers(){

    //一覧表の最初の一行を除く各行を順に処理
    $('#Grid tr').not(':first').each(function(row, tr){

        //セルCSSで指定したクラス名をもとに各セルから値を取得
        let name = $(tr).find('.cell_name').text();
        let address = $(tr).find('.cell_address').text();
        let lat = parseFloat($(tr).find('.cell_lat').text());
        let lng = parseFloat($(tr).find('.cell_lng').text());

        // 緯度と経度が数値であり、かつ範囲内にある場合にマーカーを追加
        if( lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180){

            //マーカーを追加 ポップアップには施設名と所在地を表示
            markers.addLayer(L.marker([lat, lng]).bindPopup(name + '<br>' + address));

            //一覧表の行(tr)にmouseoverイベント追加
            $(tr).on('mouseover', function() {

                //マーカーの各レイヤーを探索し、一覧表の緯度、経度が一致する場合、マーカーのポップアップを開く
                markers.eachLayer(function(layer) {
                    if (layer.getLatLng().lat == lat && layer.getLatLng().lng == lng) {
                        layer.openPopup();
                    }
                });
            });
        }
    });

    // マーカーを地図に追加
    markers.addTo(map);
    // すべてのマーカが地図に収まるよう表示範囲を調整
    map.fitBounds(markers.getBounds());
}

//マーカーを削除
function clearMarkers(){
    markers.clearLayers();
}

//「一覧画面」を読み込んだとき、もしくはフィルタ等で表示する内容が変わったときに実行
$p.events.on_grid_load = function () {

    if(!map){
        initializeMap();
        addMarkers();
    }
}

// サーバへデータを送信後、画面内容を更新後に実行
$p.events.after_set = function () {
    clearMarkers();
    addMarkers();
}

$p.events.on_grid_load は、一覧画面を読み込んだとき、もしくはフィルタ等で表示する内容が変わったときに実行されます。初回のみ地図の基本的な設定を行う初期処理を実行しています。

$p.events.after_set は、サーバへデータを送信後、画面内容を更新後に実行されます。
一覧画面において、フィルタで検索条件を指定して検索結果が表示さたタイミングと、画面の初期表示行数よりも多いデータがスクロールにより追加でロードされたタイミングでも実行されます。
ここでは、各タイミングでいったん地図上のマーカーを削除したうえで、再度一覧表上のすべての項目をマーカーとして登録しています。

開発者向け機能:スクリプト:$p.events.on_grid_load | Pleasanter
開発者向け機能:スクリプト:$p.events.after_set | Pleasanter

Leafletのマーカーの操作は編集画面でのケースと基本的には同じことをしていますが、tableの各行をマウスオーバーした際に、施設名がポップアップ表示される処理を追加しています。

一覧画面での地図埋め込み動作例

フィルタ操作

ポップアップ表示

スクロール操作

まとめ

以上のような手順でPlesanterとLeafletを組み合わせた簡単な地図表示を実現することができました。

Leafletには標準機能のほか、プラグインを導入することで更に多くの機能を実現することができます。例えば、今回の記事では省略しましたが、住所の情報から緯度、経度を変換するプラグインなども存在します。これらを組み合わせて、Pleasanter内にある住所、位置情報を活用してはいかがでしょうか。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?