1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GROWI地図表示プラグインの紹介

Posted at

オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。

今回は、GROWIプラグインとして作った地図表示プラグインを紹介します。

FireShot Capture 654 - テストページ - GROWI - localhost 654.jpg

プラグインを追加する

利用する際には、GROWIの管理画面の プラグイン にて追加してください。URLは https://github.com/goofmint/growi-plugin-embed-map です。

Admin

使い方

利用する際には、ページの中で $map と書きます。記述した場所に地図が表示されます。引数として、住所または緯度経度が指定できます。

$map(東京都千代田区丸の内1-1-1)

または位置情報を直接指定することもできます。

$map(latitude=35.681236,longitude=139.767125)

地図はOpenStreetMapを利用しています。また、ジオコーディング(住所から緯度経度を取得)にはNominatim(グローバル)と国土地理院APIを利用しています。

FireShot Capture 653 - テストページ - GROWI - localhost 653.jpg

コードについて

今回は以下のライブラリを利用しています。

そして、最初に $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: '&copy; <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をカスタマイズしましょう。

OSS開発wikiツールのGROWI | 快適な情報共有を、全ての人へ

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?