SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

JavaScriptライブラリ「Wijmo」のさまざまな部品を徹底活用(AD)

「Wijmo(ウィジモ)」のUI部品で、情報を一望できるダッシュボードページを作成しよう

JavaScriptライブラリ「Wijmo」のさまざまな部品を徹底活用 第5回

  • このエントリーをはてなブックマークに追加

Wijmoを活用したダッシュボードの実装

 ここまでで基本的な準備ができたので、以下でWijmoを活用してダッシュボードを実装していきます。

ライセンスキー設定とCollectionView

 最初に、Wijmoにライセンスキーを設定する方法と、各部品で表示するデータを管理するCollectionViewについて説明します。

[リスト3]ライセンスキー設定とCollectionViewの定義(p001-dashboard/index.js)
// Wijmoライセンスキーの設定 ...(1)
wijmo.setLicenseKey('<ライセンスキー>');
// 売上データのCollectionView ...(2)
const salesDataCV = new wijmo.collections.CollectionView(salesData, {
  // 合計列を追加 ...(2a)
  calculatedFields: {
    'sum': s => s.store1 + s.store2 + s.store3
  }
});

 ライセンスキーは(1)のwijmo.setLicenseKeyメソッドの引数として設定します。ライセンスキーを設定しないとトライアル版として動作し、トライアル版である旨が画面に表示されます。ライセンスについての詳細は公式ページを参照してください。

 (2)でCollectionViewを定義します。CollectionViewは、元となるJavaScript配列内のデータに追加の処理を行えるWijmoのクラスです。wijmo.collections.CollectionViewコンストラクターの第1引数にリスト2(2)のJavaScript配列salesDataを、第2引数にはオプションを指定します。このサンプルでは(2a)のcalculatedFieldsオプションで、store1~store3の値を合計したsumフィールド(全店舗の売上合計に対応)を定義しています。CollectionViewの詳細は公式ドキュメントを参照してください。

FlexGridによるグリッド表示

 FlexGridで売上データをグリッド表示する方法を説明します。HTML側にはリスト4の通り、FlexGridを表示するHTML要素を記述しておきます。

[リスト4]FlexGridを表示するHTML要素(p001-dashboard/index.html)
<div class="grid" id="grid-elem"></div>

 リスト4のHTML要素に対して、リスト5の処理でFlexGridを表示します。

[リスト5]FlexGridを表示する処理(p001-dashboard/index.js)
// FlexGridの表示 ...(1)
function showFlexGrid(grid) {
  // 生成済みFlexGridが指定された場合は破棄する ...(2)
  if (grid != null) grid.dispose();
  // 新しいFlexGridを生成 ...(3)
  const newGrid = new wijmo.grid.FlexGrid('#grid-elem', {
    itemsSource: salesDataCV,
    autoGenerateColumns: false,
    isReadOnly: true,
    columns: [
      { binding: 'date', header: '年月日', width: 110 },
      { binding: 'store1', header: '本店', width: 90 },
      { binding: 'store2', header: '駅前店', width: 90 },
      { binding: 'store3', header: '空港店', width: 90 },
      { binding: 'sum', header: '合計', width: 90 }
    ]
  });
  // 生成したFlexGridを返却 ...(4)
  return newGrid;
}
// FlexGridの表示を実行 ...(5)
let grid = showFlexGrid(null);

 (1)のshowFlexGrid関数でFlexGridを表示します。あとでFlexGridを再描画する際に一度破棄する必要があるため、関数の引数でFlexGridの変数を受け取り、nullでない場合には(2)のdisposeメソッドで破棄するようにします。(3)で新しいFlexGridを生成して、その戻り値を(4)で返却します。wijmo.grid.FlexGridコンストラクターの第1引数に表示先HTML要素のセレクター(ここではリスト4のHTML要素のIDを「#grid-elem」と指定)、第2引数には表2に示すオプションを指定します。

表2 リスト5(3)で指定するFlexGridのオプション
No. 項目名 意味
1 itemsSource 表示するデータ salesDataCV(CollectionView)
2 autoGenerateColumns 列を自動生成するか false(しない)
3 isReadOnly 読み取り専用にするか true(する)
4 columns 表示する列の指定 (表3を参照)

 columnsでは表示する列を指定します。指定内容は表3の通りです。ここではbindingにdate、store1~store3、およびリスト3(2a)で定義した合計列sumを指定して、日次の各店舗の売上と合計売上を表に表示します。

表3 リスト5(3)で指定するcolumnsの内容
No. 項目名 意味
1 binding データ属性の名前
2 header ヘッダー行に表示する文言
3 width 列の幅

 最後に(5)でshowFlexGrid関数を実行してFlexGridを表示するとともに、FlexGridに対応した変数gridを戻り値で受け取って保持しておきます。この変数はあとで再描画の時に使います。

FlexChartによるチャート表示

 次に、FlexChartで売上データをチャート(棒グラフ)に表示していきます。FlexGrid同様、HTML側にはFlexChartを表示するHTML要素をリスト6の通り記述します。

[リスト6]FlexChartを表示するHTML要素(p001-dashboard/index.html)
<div class="chart" id="chart-elem"></div>

 FlexChartを表示する処理の実装はリスト7の通りです。

[リスト7]FlexChartを表示する処理(p001-dashboard/index.js)
// FlexChartの表示 ...(1)
function showFlexChart(chart) {
  // 生成済みFlexChartが指定された場合は破棄する ...(2)
  if (chart != null) chart.dispose();
  // 新しいFlexChartを生成 ...(3)
  const newChart = new wijmo.chart.FlexChart('#chart-elem', {
    itemsSource: salesDataCV,
    bindingX: 'date',
    series: [
      { binding: 'store1', name: '本店' },
      { binding: 'store2', name: '駅前店' },
      { binding: 'store3', name: '空港店' }
    ]
  });
  // 生成したFlexChartを返却 ...(4)
  return newChart;
}
// FlexChartの表示を実行 ...(5)
let chart = showFlexChart(null);

 (1)のshowFlexChart関数でFlexChartを表示します。関数の引数でFlexChartの変数を受け取り、nullでない場合に(2)で破棄する処理は、FlexGridの処理(リスト5)と同様です。(3)で新しいFlexChartを生成して、その戻り値を(4)で返却します。wijmo.grid.FlexChartコンストラクターの第1引数に表示先HTML要素(リスト6)を表すセレクター「#chart-elem」、第2引数には表4に示すオプションを指定します。

表4 リスト7(3)で指定するFlexChartのオプション
No. 項目名 意味
1 itemsSource 表示するデータ salesDataCV(CollectionView)
2 bindingX X軸に対応するデータ属性名 date
3 series チャートに表示するデータ系列の配列 (後述)

 seriesにはチャートのデータ系列を配列で指定します。配列要素のbindingにデータ属性名(ここではstore1~store3)、nameにはデータ属性の名前(ここでは店舗名)をそれぞれ指定します。

 最後に(5)でshowFlexChart関数を実行してFlexChartを表示します。戻り値で受け取ったFlexChartの変数chartは、FlexGridと同様、再描画時に利用します。

RadialGaugeによるゲージ表示

 各店舗のこれまでの売上を合計して、目標額に対する売上達成率をRadialGauge(円形のゲージ)に表示するようにします。1つのゲージに対応するHTML要素はリスト8の通りです。(1)には売上目標と売上合計の文言を表示し、(2)にRadialGaugeを表示します。このようなHTML要素を4つ(3店舗+合計の分)記述します。

[リスト8]売上達成率を表示するHTML要素(p001-dashboard/index.html)
<div class="gauge-title">本店</div>
<div class="gauge-sales-status" id="gauge-sales-status1"></div> <!--(1)-->
<div class="gauge" id="gauge-elem1"></div> <!--(2)-->

 RadialGaugeを初期化する処理はリスト9の通りです。wijmo.gauge.RadialGaugeコンストラクターの第1要素にHTML要素のセレクターを設定して実行します。第2要素にオプションを指定することでゲージの表示などをカスタマイズすることができます。今回は各ゲージにgetTextオプションでコールバック関数getTextCallback(1)を指定し、ゲージに表示する文字列に%の記号を連結しています。さらに合計のゲージ(gaugeAll)ではpointerオプションを指定して、ゲージの色を赤にしています。

[リスト9]RadialGaugeを初期化する処理(p001-dashboard/index.js)
// RadialGaugeの初期化
const gauge1 = new wijmo.gauge.RadialGauge('#gauge-elem1',{
  getText: getTextCallback,
});
const gauge2 = new wijmo.gauge.RadialGauge('#gauge-elem2',{
  getText: getTextCallback,
});
const gauge3 = new wijmo.gauge.RadialGauge('#gauge-elem3',{
  getText: getTextCallback,
});
const gaugeAll = new wijmo.gauge.RadialGauge('#gauge-elem-all', {
  getText: getTextCallback,
  pointer: { color: '#ff0000' }
});
// RadialGaugeに表示する文字列に「%」を連結するコールバック関数 ...(1)
function getTextCallback(gauge, part, value, text) {
  return `${text}%`;
}

 売上達成率を表示する処理の実装はリスト10の通りです。

[リスト10]売上達成率を表示する処理(p001-dashboard/index.js)
// 売上達成率の計算と表示 ...(1)
function showSalesPercents() {
  // 売上合計 ...(2)
  const items = salesDataCV.items;
  const salesSum1 = items.reduce((s, elem) => s + elem.store1, 0);
  const salesSum2 = items.reduce((s, elem) => s + elem.store2, 0);
  const salesSum3 = items.reduce((s, elem) => s + elem.store3, 0);
  const salesSumAll = items.reduce((s, elem) => s + elem.sum, 0);
  // 売上目標 ...(3)
  const salesTarget1 = salesTarget.store1;
  const salesTarget2 = salesTarget.store2;
  const salesTarget3 = salesTarget.store3;
  const salesTargetAll = salesTarget1 + salesTarget2 + salesTarget3;
  // 売上達成率をゲージに設定 ...(4)
  gauge1.value = salesSum1 / salesTarget1 * 100;
  gauge2.value = salesSum2 / salesTarget2 * 100;
  gauge3.value = salesSum3 / salesTarget3 * 100;
  gaugeAll.value = salesSumAll / salesTargetAll * 100;
  // 売上目標と売上合計を表示 ...(5)
  document.getElementById('gauge-sales-status1').textContent
    = `¥${Intl.NumberFormat('ja-JP').format(salesSum1)} /
       ¥${Intl.NumberFormat('ja-JP').format(salesTarget1)}`;
(略)
}
// 売上達成率の計算と表示を実行 ...(6)
showSalesPercents();

 (1)のshowSalesPercents関数で売上達成率(RadialGaugeと文言)を表示します。(2)は売上合計の計算です。CollectionViewのitemsプロパティからデータ配列を取得して、reduceメソッドでデータ配列のstore1~store3、およびsumを合計します。(3)では各店舗の売上目標を取得して、それらを合計して全体の売上目標とします。ここまで計算した売上合計と売上目標から割合を計算して、(4)でゲージに設定します。(5)は売上目標と売上合計を文字で表示する処理です。最後に(6)でshowSalesPercents関数を実行して表示を行います。

売上データ追加と再描画の処理

 このサンプルでは「売上データを追加」ボタンをクリックするとランダムで売上データを追加し、その内容が表示に反映されるようにします。処理内容はリスト11の通りです。

[リスト11]売上データを追加して表示に反映する処理(p001-dashboard/index.js)
// ランダムな売上を取得する処理 ...(1)
function getRandomSales() {
  return Math.floor(Math.random() * 150000) + 50000;
}
// 売上データを追加する処理 ...(2)
function addSalesData() {
  const items = salesDataCV.items;
  // 31日までデータ追加済みの場合は処理しない ...(3)
  if (items.length >= 31) return;
  // 新しい日のデータを追加 ...(4)
  const newDay = items.length + 1;
  items.push({
    'date': `2024/03/${newDay < 10 ? '0' + newDay : newDay}`,
    'store1': getRandomSales(),
    'store2': getRandomSales(),
    'store3': getRandomSales()
  });
  // FlexGrid、FlexChartを更新 ...(5)
  grid = showFlexGrid(grid);
  chart = showFlexChart(chart);
  // 売上達成率を更新 ...(6)
  showSalesPercents();
}

 (1)はランダムな売上を取得する処理です。ボタンクリック時に売上データを追加する処理は(2)で、31日を超えるデータを追加しないように(3)で判定後、(4)で新しいデータを追加します。新しいデータのdate属性は既存データの続きの年月日、store1~store3属性には(1)の処理で取得したランダムな売上を設定します。

 売上データ追加後、(5)でFlexGridとFlexChartを更新します。現在表示されているFlexGridとFlexChartに対応する変数grid、chartを渡すことで、それまでの表示をいったん破棄して新たに生成します。それまでの表示を破棄するのは、追加されたデータを表示に反映するためです。最後に(6)で、売上達成率を表示するRadialGaugeとテキストを更新します。

まとめ

 本記事では、WijmoのUI部品であるFlexGrid、FlexChart、RadialGauge、およびデータを操作するCollectionViewを利用して、店舗の売上達成状況を想定したダッシュボードWebページのサンプルを作成しました。各UI部品の得意分野を組み合わせることにより、表現力豊かにデータを可視化できます。

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
JavaScriptライブラリ「Wijmo」のさまざまな部品を徹底活用連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

提供:メシウス株式会社

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/19341 2024/04/25 12:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング