2024年8月20日火曜日

amChartsをOracle APEXのアプリケーションに組み込む

amChartsをOracle APEXのアプリケーションに組み込んでみます。

Oracle JETやその他のチャート描画ライブラリの組み込み作業で表示したチャートと、同じチャートを表示してみます。


直接amChartsで描画



amChartsのGetting startedを参照して、作業を進めます。

ページ・プロパティJavaScriptファイルURLに以下を記述します。

https://cdn.amcharts.com/lib/5/index.js
https://cdn.amcharts.com/lib/5/xy.js
https://cdn.amcharts.com/lib/5/themes/Animated.js


静的コンテンツのリージョンの名前amChartsとし、ソースHTMLコードに以下を記述します。

<div id="myChart" class="h400"></div>


チャートに描画するデータを保持するページ・アイテムとしてP1_VALUEを作成します。タイプ非表示です。

ページ・アイテムP1_VALUE計算を作成し、ページの描画前にデータを設定します。計算タイプとしてSQL問合せ(単一の値を返す)を選択し、SQL問合せに以下を記述します。
select
    json_arrayagg(
        json_object(
            'ename' value ename,
            'sal'     value sal
        )
    order by empno asc )
from emp where deptno = 10

チャートを描画するJavaScriptのコードを、ページ・プロパティページ・ロード時に実行に記述します。

amChartsのDemosに含まれるClustered Bar Chartのコードを簡素にしています。

am5.ready(function() {
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("myChart");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: "panX",
wheelY: "zoomX",
paddingLeft:0,
layout: root.verticalLayout
}));
// Data
const value = apex.item("P1_VALUE").getValue();
var data = JSON.parse(value);
// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "ename",
renderer: am5xy.AxisRendererY.new(root, {
inversed: true,
cellStartLocation: 0.1,
cellEndLocation: 0.9,
minorGridEnabled: true
})
}));
yAxis.data.setAll(data);
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererX.new(root, {
strokeOpacity: 0.1,
minGridDistance: 50
}),
min: 0
}));
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
xAxis: xAxis,
yAxis: yAxis,
valueXField: "sal",
categoryYField: "ename",
sequencedInterpolation: true,
fill: am5.color('#309fdb')
}));
series.columns.template.setAll({
height: am5.p50,
strokeOpacity: 0,
});
series.data.setAll(data);
series.appear();
// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
chart.appear(1000, 100);
}); // end am5.ready()


以上で実装は完了です。ページを実行すると以下のように表示されます。




テンプレート・コンポーネントの作成




amChartsのバー・チャートを描画するテンプレート・コンポーネントについて、設定内容を説明します。

テンプレート・コンポーネントの名前amCharts Bar Chartとしました。テンプレート部分には以下を記述しています。

<div class="#CSS_CLASSES#">
<a-amcharts-bar-chart id="#APEX$DOM_ID#" categoryY="#CATEGORY_Y#" valueX="#VALUE_X#" value="#VALUE#" color="#COLOR#" width="#WIDTH#" height="#HEIGHT#"></a-amcharts-bar-chart>
</div>

カスタム属性としてCSS ClassesCategory Y, Value X, ValueColorWidthHeightを作成しています。Category YはY軸となる(Valueに含まれる)属性で、今回の実装ではenameを指定します。Value XはX軸となる値の属性で、今回の実装ではsalです。Valueタイプセッション・ステート値ColorカラーWidthHeightは両方とも整数です。


ディレクトリjsファイル名script.jsとして、カスタム要素a-amcharts-bar-chartの実装を記述します。

(function (debug) {
"use strict";
class amChartsBarChart extends HTMLElement {
chart;
chartId;
constructor() {
super();
this.chartId = new Date().getTime();
debug.info("%s, constructor", this.chartId);
}
connectedCallback() {
debug.info("%s, %s, connectedCallback, %s", this.chartId, new Date().getTime(), this.isConnected);
if (this.isConnected) {
/* prepare div for chart region */
var chart;
const categoryY = this.getAttribute("categoryY");
const valueX = this.getAttribute("valueX");
const value = this.getAttribute("value");
const color = this.getAttribute("color");
const div = document.createElement("div");
const width = this.getAttribute("width");
if ( width ) {
div.classList.add(`w${width}`);
};
const height = this.getAttribute("height");
if ( height ) {
div.classList.add(`h${height}`);
};
this.appendChild(div);
/* draw chart with amCharts */
am5.ready(function() {
var root = am5.Root.new(div);
// Set themes
root.setThemes([
am5themes_Animated.new(root)
]);
// Create chart
chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: "panX",
wheelY: "zoomX",
paddingLeft:0,
layout: root.verticalLayout
}));
// Data
var data = JSON.parse(value);
debug.info(data);
// Create axes
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: categoryY,
renderer: am5xy.AxisRendererY.new(root, {
inversed: true,
cellStartLocation: 0.1,
cellEndLocation: 0.9,
minorGridEnabled: true
})
}));
yAxis.data.setAll(data);
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererX.new(root, {
strokeOpacity: 0.1,
minGridDistance: 50
}),
min: 0
}));
// Add series
const seriesConfig = {
xAxis: xAxis,
yAxis: yAxis,
valueXField: valueX,
categoryYField: categoryY,
sequencedInterpolation: true
};
if ( color ) {
seriesConfig.fill = am5.color(color);
};
var series = chart.series.push(am5xy.ColumnSeries.new(root, seriesConfig));
series.columns.template.setAll({
height: am5.p50,
strokeOpacity: 0,
});
series.data.setAll(data);
series.appear();
// Make stuff animate on load
chart.appear(1000, 100);
}); // end am5.ready()
this.chart = chart;
}
}
disconnectedCallback() {
debug.info("%s, %s, disconnectedCallback", this.chartId, new Date().getTime());
if (this.firstChild) {
this.removeChild(this.firstChild);
}
}
}
document.addEventListener('DOMContentLoaded', () => {
if ( window.customElements.get("a-amcharts-bar-chart") === undefined ) {
debug.info("define custom element");
window.customElements.define("a-amcharts-bar-chart", amChartsBarChart);
};
});
})(apex.debug);
view raw script.js hosted with ❤ by GitHub

ロードするファイルURLJavaScriptに以下を記述します。

https://cdn.amcharts.com/lib/5/index.js
https://cdn.amcharts.com/lib/5/xy.js
https://cdn.amcharts.com/lib/5/themes/Animated.js
#PLUGIN_FILES#js/script#MIN#.js


以上でテンプレート・コンポーネントは完成です。

リージョンにamChartsのテンプレート・コンポーネントを実装します。

ページ・アイテムP2_VALUEは、最初に作成したP1_VALUEと同じ設定で作成します。

識別名前amChartsタイプamCharts Bar Chartとします。


リージョンの属性を開き、Category YとしてenameValue XとしてsalValueとしてP2_VALUEColorとして#309fdbを設定します。Height400とします。


以上で実装は完了です。ページを実行すると以下のように表示されます。




対話モード・レポートへの組み込み




対話モード・レポートソース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を選択し、識別タイプamCharts Bar Chartに変更します。

設定Category YenameValue XsalValueVALUEColor#309fdbを設定します。Width400Height200を設定します。


以上で実装は完了です。ページを実行すると以下のように表示されます。


今回の記事は以上になります。

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

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