2023年1月31日火曜日

APEXでCytoscape.jsを使ってみる

 以前にグラフ問合せを扱った記事を書いたことがありますが、問い合わせの結果をレポート、つまり表形式で印刷していました。それではイマイチなので、APEXでCytoscape.jsを使う方法を確認してみました。

Cytoscape.jsのページに記載されているGetting startedをAPEXのアプリケーションとして実装してみました。Getting Startedをそのまま埋め込むのではなく、アプリケーションのサンプルとして役立つように以下の実装を加えています。

  1. elementsとstyleは静的なJSONファイルではなく、サーバー側で生成した値を使う。
  2. ページ・ロード時にグラフを描画するのではなく、ブラウザのイベントより(今回はボタンの押下)生成する。
作成したアプリケーションは以下のように動作します。


簡単なアプリケーションですが、以下に実装を紹介します。

最初に空のアプリケーションを作成します。実装はホーム・ページに行います。

ページ・プロパティのJavaScriptファイルURLとして、Cytoscape.jsを指定します。バージョンなどは変わるため、実装時はCytoscape.jsのホームページよりリンクを取得してください。

https://unpkg.com/cytoscape@3.23.0/dist/cytoscape.min.js

グラフを描画する領域を作成します。

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

作成したリージョンの識別タイトルCytoscapeタイプ静的コンテンツとします。ソースHTMLコードとして以下を記述します。

<div id="cy"></div>

装飾は不要なので、外観テンプレートとしてBlank with Attributesを選択します。

HTMLコードとして記述したid="cy"のDIV要素にCytoscapeによるグラフが描画されます。描画領域をCSSで指定します。

ページ・プロパティのCSSインラインに以下を記述します。

#cy {
  width: 300px;
  height: 300px;
  display: block;
}

サーバー側でグラフのデータを生成するプロセスを作成します。

データを生成するプロセスはAjaxコールバックとして作成します。

識別名前GET_DATAとします。タイプとしてコードの実行を選択し、ソースPL/SQLコードとして以下を記述します。Getting Startedに記述されているelementsとstyleと同じデータを出力しています。

declare
l_response clob;
l_response_json json_object_t;
l_data_array json_array_t;
l_data json_object_t;
l_style_array json_array_t;
l_style json_object_t;
begin
/* elementsの作成 */
l_data_array := json_array_t();
l_data := json_object_t();
l_data.put('data', json_object_t(
json_object(
'id' value 'a'
)));
l_data_array.append(l_data);
l_data := json_object_t();
l_data.put('data', json_object_t(
json_object(
'id' value 'b'
)));
l_data_array.append(l_data);
l_data := json_object_t();
l_data.put('data', json_object_t(
json_object(
'id' value 'ab'
,'source' value 'a'
,'target' value 'b'
)));
l_data_array.append(l_data);
/* sytleの作成 */
l_style_array := json_array_t();
l_style := json_object_t();
l_style.put('style', json_object_t(
json_object(
'background-color' value '#666'
,'label' value 'data(id)'
)));
l_style_array.append(l_style);
l_style := json_object_t();
l_style.put('selector','node');
l_style.put('style', json_object_t(
json_object(
'background-color' value '#666'
,'label' value 'data(id)'
)));
l_style_array.append(l_style);
l_style := json_object_t();
l_style.put('selector','edge');
l_style.put('style', json_object_t(
json_object(
'width' value 3
,'line-color' value '#ccc'
,'target-arrow-color' value '#ccc'
,'target-arrow-shape' value 'triangle'
,'curve-style' value 'bezier'
)));
l_style_array.append(l_style);
/* 応答となるJSONを生成 */
l_response_json := json_object_t();
l_response_json.put('elements', l_data_array);
l_response_json.put('style', l_style_array);
l_response := l_response_json.to_clob();
apex_debug.info(l_response);
htp.p(l_response);
end;



Cytoscape.jsを呼び出してグラフを描画する処理は、APEXアクションとして実装します。

JavaScriptファンクションおよびグローバル変数の宣言に、以下を記述します。

var cy;
const RENDER_CY = {
name: "render-cy",
action: (event, element, args) => {
let result = apex.server.process("GET_DATA", {
x01: "get_data"
});
result.done( (data) => {
cy = cytoscape({
container: document.getElementById('cy'), // container to render in
elements: data.elements,
style: data.style,
layout: {
name: 'grid',
rows: 1
}
})
});
}
};
view raw render-cy.js hosted with ❤ by GitHub

また、ページ・ロード時に実行に以下の1行を記述します。

apex.actions.add([RENDER_CY]);


作成したアクションrender-cyを呼び出すボタンを作成します。

リージョンCytoscapeにボタンを作成します。

識別ボタン名RENDERラベルRenderとします。レイアウト位置としてNextを選びます。

動作アクションとして動的アクションで定義を選択し、詳細カスタム属性として以下を記述します。

data-action="#action$render-cy"


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

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

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