Oracle JETやその他のチャート描画ライブラリの組み込み作業で表示したチャートと、同じチャートを表示してみます。今回はカスタム要素は作成せず、Observable PlotはESモジュールとして読み込んで実装してみます。
チャートを描画するリージョンや列に埋め込まれた(type="module"の)スクリプトは、遅延ロードが完了したときに実行されます。そのため、対話モード・レポートでページ送りを行なったときでもチャートが正しく描画されます。ただし、これは描画にSVGが使われている場合に限られるようです。Canvas要素にチャートを書き込むタイプのライブラリでは、対話モード・レポートで遅延ロードが行われるとチャートは表示されません。
直接Observable Plotで描画
jsDelivrへアクセスし、Observable PlotのESモジュールを指すURLを取得します。TypeにESMを選択し、VersionはLatest Majorとします。Copy URLを実行します。
スクリプトにESモジュールのURLを直書きする代わりに、別名を指定できるようにします。
ページ・プロパティのHTMLヘッダーにimportmapを記述します。Observable Plotは、別名observablehqを指定してインポートできるようになります。
<script type="importmap">
{
"imports": {
"observablehq": "https://cdn.jsdelivr.net/npm/@observablehq/plot/+esm"
}
}
</script>
Observable PlotのGetting startedを参考にして、div要素にチャートを描画します。
ページ・アイテムP1_VALUEに計算を作成し、ページの描画前にデータを設定します。計算のタイプとしてSQL問合せ(単一の値を返す)を選択し、SQL問合せに以下を記述します。
select
json_arrayagg(
json_object(
'ename' value ename,
'sal' value sal
)
order by empno asc
)
from emp where deptno = 10
静的コンテンツのリージョンの名前をObservable Plotとし、ソースのHTMLコードに以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="myChart""></div> | |
<script type="module"> | |
import * as observablehq from 'observablehq'; | |
// "apex.items.ITEM_NAME.value" is not available inside module. | |
// const value = apex.items.P1_VALUE.value; | |
const value = apex.item("P1_VALUE").getValue(); | |
var data = JSON.parse(value); | |
const plot = observablehq.plot({ | |
label: null, | |
width: 400, | |
marginLeft: 60, | |
marks: [ | |
observablehq.barX(data, { x: "sal", y: "ename", fill: "#309fdb" } ) | |
] | |
}); | |
const div = document.getElementById("myChart"); | |
div.append(plot); | |
</script> |
以上で実装は完了です。ページを実行すると以下のように表示されます。
対話モード・レポートへの組み込み
対話モード・レポートのページのページ・プロパティのHTMLヘッダーに、先ほどと同じimportmapを記述します。
対話モード・レポートのソースのSQL問合せとして以下を記述します。
select
dname,
json_arrayagg(
json_object(
'ename' value ename,
'sal' value sal
)
order by empno asc
) value,
'' chart
from emp_dept_v group by dname
対話モード・レポートの列CHARTを選択します。識別のタイプはプレーン・テキストです。
列の書式のHTML式として以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="#APEX$DOM_ID#" class="w400"><div> | |
<script type="module"> | |
import * as observablehq from 'observablehq'; | |
const value = '#VALUE!RAW#'; | |
var data = JSON.parse(value); | |
const plot = observablehq.plot({ | |
label: null, | |
width: 400, | |
marginLeft: 60, | |
marks: [ | |
observablehq.barX(data, { x: "sal", y: "ename", fill: "#309fdb" } ) | |
] | |
}); | |
const div = document.getElementById("#APEX$DOM_ID#"); | |
div.append(plot); | |
</script> |
置換文字列#APEX$DOM_ID#はAPEX 24.1から提供されている新機能で、テンプレート・ディレクティブやテンプレート・コンポーネント毎にユニークな値に置換されます。
テンプレート・コンポーネントの作成
Observable Plotのバー・チャートをテンプレート・コンポーネントとして作成します。カスタム要素は作成しません。
テンプレート・コンポーネントの名前はObservable Plot Bar Chartとしました。テンプレートの部分には以下を記述しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="#APEX$DOM_ID#" class="#CSS_CLASSES#"><div> | |
<script type="module"> | |
import * as observablehq from 'observablehq'; | |
/* plot chart */ | |
let config = { | |
label: null, | |
marks: [] | |
}; | |
// define plot area. | |
const width = "#WIDTH#"; | |
if ( width ) { | |
config.width = Number(width); | |
}; | |
const height = "#HEIGHT#"; | |
if ( height ) { | |
config.height = Number(height); | |
}; | |
const marginTop = "#MARGIN_TOP#"; | |
if ( marginTop ) { | |
config.marginTop = Number(marginTop); | |
}; | |
const marginRight = "#MARGIN_RIGHT#"; | |
if ( marginRight ) { | |
config.marginRight = Number(marginRight); | |
}; | |
const marginLeft = "#MARGIN_LEFT#"; | |
if ( marginLeft ) { | |
config.marginLeft = Number(marginLeft); | |
}; | |
const marginBottom = "#MARGIN_BOTTOM#"; | |
if ( marginBottom ) { | |
config.marginBottom = Number(marginBottom); | |
}; | |
// define bar. | |
const groups = "#GROUPS#"; | |
apex.debug.info(groups); | |
const xy = groups.split(","); | |
let bar = { | |
x: xy[0].trim(), | |
y: xy[1].trim() | |
}; | |
const color = "#COLOR#"; | |
if ( color ) { | |
bar.fill = color; | |
}; | |
// data | |
const data = JSON.parse('#VALUE#'); | |
const orientation = "#ORIENTATION#"; | |
if ( orientation === null || orientation === "horizontal" ) { | |
config.marks.push( | |
observablehq.barX(data, bar) | |
); | |
} | |
else | |
{ | |
config.marks.push( | |
observablehq.barY(data, bar) | |
); | |
}; | |
/* draw chart */ | |
apex.debug.info(config); | |
const plot = observablehq.plot(config); | |
document.getElementById("#APEX$DOM_ID#").appendChild(plot); | |
</script> |
カスタム属性としてCSS Classes、Groups、Value、Color、Orientationを作成しています。Groupsのタイプは、セッション・ステート値ではなくテキストとしています。
加えて、チャートの表示領域を規定するWidth、Height、Margin Top、Margin Right、Margin Left、Margin Bottomをカスタム属性として作成しています。これらは全て整数です。
チャートの向きの指定であるOrientationの静的LOVは、horizontalの戻り値としてhorizontal、verticalの戻り値としてverticalを設定します。
テンプレート・コンポーネントにはimportmapを設定する方法がありません。そのため、設定は以上で完了です。このテンプレート・コンポーネントを使用するページでは、HTMLヘッダーにimportmapを記述する必要があります。
対話モード・レポートにObservable Plotのテンプレート・コンポーネントを実装します。
列CHARTを選択し、識別のタイプをObservable Plot Bar Chartとします。
CSS Classesとしてw400、Groupsとしてsal,ename、ValueとしてVALUE、Colorとして#309fdb、Orientationとしてhorizontalを設定します。チャートの描画領域としてWidthに400、Margin Leftに60を設定します。
今回の記事は以上になります。
作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/integrating-observable-plot-esm.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/integrating-observable-plot-esm.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完