2023年2月13日月曜日

Mapbox GL Drawを使ってマップ・リージョンに図形を書く

 ポーランドのPretius社のLech Cieślikさんが、マップ・リージョンに図を書く方法を紹介されています。

Drawing objects on maps in Oracle APEX - MapLibre vs OpenLayers

記事に従ってアプリケーションを作ってみました。


アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。

名前Drawing on Mapとしました。アプリケーションの作成を実行します。


アプリケーションが作成されたら、ページ・デザイナホーム・ページを開きます。

とりあえず地図が表示されればよいので、最小限の設定で地図のリージョンを作成します。

新規にリージョンを作成します。

識別タイトルMapタイプマップを選択します。ソース位置ローカル・データベースタイプSQL問合せとします。以下のSQLを記述します。皇居の緯度経度です。

select 35.6769883 lat, 139.7588499 lon from dual


レイヤー識別名前Sampleレイヤー・タイプポイントとします。

ソースの位置リージョン・ソース列のマッピングジオメトリ列のデータ型として経度/緯度を選択し、緯度列LON経度列LATを指定します。


マップ・リージョンは以上で作成できました。

ページ・プロパティの設定を行います。

JavaScriptファイルURLとして、Mapbox GL Drawが実装されているファイルを指定します。

https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.4.0/mapbox-gl-draw.js

Pretiusさんの元記事はv1.2.0をロードしていますが、Mapboxのサイトの例ではv1.4.0をロードしていたので、v1.4.0を指定するようにしています。


CSSファイルURLとして以下を指定します。

https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.4.0/mapbox-gl-draw.css

Mapbox GL Drawを初期化する処理は、APEXアクションとして実装します。

JavaScriptファンクションおよびグローバル変数の宣言に以下を記述します。draw.createにだけコールバックを定義しています。この他にdraw.updatedraw.deleteにコールバックを定義できます。

/*
* This code is based on the article wrtten by Lech Cieślik, Pretius.
* Drawing objects on maps in Oracle APEX - MapLibre vs OpenLayers
* https://pretius.com/blog/maplibre-vs-openlayers/
*/
var map, draw;
/*
* MapboxのDrawプラグインの初期化。
*/
const DRAW_INIT = {
name: "draw-init",
action: (event, element, args) => {
//Get MapLibre GL JS map object
map = apex.region(element.id).getMapObject();
//Add Draw plug-in.
draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
point: true,
line_string: true,
polygon: true,
trash: true
}
});
//Add Control to map
map.addControl(draw, 'top-left');
//Fix Mapbox - MapLibre issue
$('.mapboxgl-ctrl-group.mapboxgl-ctrl').addClass('maplibregl-ctrl maplibregl-ctrl-group');
// 図形が作成されたときに呼び出される。
map.on("draw.create", (e) => {
apex.items.P1_COORDINATE.setValue(
JSON.stringify(e.features[0].geometry)
);
});
}
};
/*
* アクションの初期化。
*/
apex.jQuery(window).on('theme42ready', () => {
apex.actions.add([DRAW_INIT]);
});


作成された図形の座標を出力するページ・アイテムを作成します。

ページ・アイテムの識別名前P1_COORDINATEタイプテキスト領域とします。ラベルCoordinateとします。


Mapbox GL Drawを初期化する処理を、動的アクションより呼び出します。

マップ・リージョンに動的アクションを作成します。

識別名前Init Mapbox GL Drawとします。タイミングイベントとして、マップが初期化されました[マップ]を選択します。選択タイプリージョンリージョンとしてMapを選択します。


実行するTRUEアクションとしてJavaScriptコードの実行を選択し、コードとして以下を記述します。APEXアクションとして定義したdraw-initを呼び出します。

apex.actions.invoke("draw-init", null, this.triggeringElement);


以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

元記事はOpenLayersを使った方法も紹介しています。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/drawing-on-map.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。