オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。
今回は、GROWIプラグインとして作った地図表示プラグインを紹介します。
プラグインを追加する
利用する際には、GROWIの管理画面の プラグイン
にて追加してください。URLは https://github.com/goofmint/growi-plugin-embed-map
です。
使い方
利用する際には、ページの中で $map
と書きます。記述した場所に地図が表示されます。引数として、住所または緯度経度が指定できます。
$map(東京都千代田区丸の内1-1-1)
または位置情報を直接指定することもできます。
$map(latitude=35.681236,longitude=139.767125)
地図はOpenStreetMapを利用しています。また、ジオコーディング(住所から緯度経度を取得)にはNominatim(グローバル)と国土地理院APIを利用しています。
コードについて
今回は以下のライブラリを利用しています。
そして、最初に $map
と記述があれば、地図表示用のHTMLタグを出力します。
// 1ページ中に複数の地図を表示できるようにするため、IDをランダム生成
const domId = `map-${Math.random().toString(36).slice(-8)}`;
if (n.type === 'leafGrowiPluginDirective' && n.name === 'map') {
const address = Object.keys(n.attributes)[0]; // 住所
let { latitude, longitude } = n.attributes; // 位置情報
n.type = 'html';
n.value = `<div id="${domId}" style="height: 400px; width: 100%"></div>`;
let map: null | L.Map = null;
}
そして、このHTMLがレンダリングされた後に、地図を表示します。
let map: null | L.Map = null;
const id = setInterval(async() => {
// DOMが存在するか確認
const mapDom = document.querySelector(`#${domId}`);
if (mapDom == null) {
return;
}
clearInterval(id);
// すでに地図が表示されている場合は何もしない
if (map != null) return;
// 位置情報を取得する
const geoPoint = await getGeoPoint(address, latitude, longitude);
if (geoPoint === null) throw new Error(`Failed to get geo point ${address}`);
latitude = geoPoint.latitude;
longitude = geoPoint.longitude;
// 地図表示
map = L.map(domId).setView([parseFloat(latitude), parseFloat(longitude)], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
}).addTo(map);
// マーカー表示
const marker = L.marker([parseFloat(latitude), parseFloat(longitude)]);
marker.bindPopup(address).openPopup();
marker.addTo(map);
}, 1000);
位置情報の取得は以下のようになります。
interface GeoPoint {
longitude: string;
latitude: string;
}
const getGeoPoint = async({ address, latitude, longitude }: any) => {
if (latitude && longitude) {
return {
latitude,
longitude,
};
}
if (address == null) return null;
const geoPointGSI = await getGeoPointByGSI(address as string);
if (geoPointGSI) return geoPointGSI;
return getGeoPointByOSM(address as string);
};
// Nominatimから位置情報を取得
const getGeoPointByOSM = async(address: string): Promise<GeoPoint | null> => {
const url = `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(address)}&format=json`;
const res = await fetch(url);
const json = await res.json();
if (json.length > 0) {
return {
longitude: json[0].lon,
latitude: json[0].lat,
};
}
return null;
};
// 国土地理院APIから位置情報を取得
const getGeoPointByGSI = async(address: string): Promise<GeoPoint | null> => {
const res = await fetch(`https://msearch.gsi.go.jp/address-search/AddressSearch?q=${encodeURIComponent(address)}`);
const json = await res.json();
if (json.length > 0) {
return {
longitude: json[0].geometry.coordinates[0],
latitude: json[0].geometry.coordinates[1],
};
}
return null;
};
まとめ
GROWIプラグインを使うと、表示を自由に拡張できます。足りない機能があれば、どんどん追加できます。ぜひ、自分のWikiをカスタマイズしましょう。