SetRendered と GET_Rendered を活用した「円グラフのカスタムユニット」を作ってみよう

この記事は公開日より4年以上経過しているため、現在の内容と異なる可能性があります。


一般的にグラフをサイトに貼り付けるのであれば、上記のようにエクセルで描いたグラフをキャプチャした画像を用意して画像ユニットにアップするのが一般的かと思いますが、a-blog cms ならではのカスタムユニットでデータを登録できるような管理ページを用意して、chart.js という JavaScript を活用してグラフを表示できるようなものを作ってみます。

このハンズオンでは、SetRendered と GET_Rendered の利用方法も学ぶことができますので、ぜひチャレンジしてみてください。

グラフを描くことができる JavaScript ライブラリ「chart.js」

グラフの表示には「chart.js」という JavaScript ライブラリを利用します。円グラフだけでなく、棒グラフや折れ線グラフなども設定次第では描くことができます。



カスタムユニット

テキストユニットではテキストの入力欄が1つ、画像ユニットであれば画像を1枚アップできるような単機能なユニットになりますが、カスタムユニットを利用するとユニットに自由にカスタムフィールドやカスタムフィールドグループを設定することができます。

今回のグラフであれば、以下のようにグラフ名、サイズ、配置の設定と、グループでラベル・色・値を複数設定しグラフ表示に必要な情報を全てユニット内に登録できるような入力欄を実装します。

カスタムユニットは、少しだけカスタムフィールドと記述が違いますので、カスタムフィールドメーカー を利用する際には、ラジオボタンでカスタムユニット・カスタムユニット(フィールドグループ)を選択してください。



管理ページ側の実装

/themes/使用中のテーマ/admin/entry/unit/extend.html に下記ソースコードを追加してください。

<!-- BEGIN custom_chart -->
<h2 class="acms-admin-admin-title2">円グラフ</h2>
<table class="acms-admin-table-admin-edit" style="margin-bottom: 10px;">
  <tr>
    <th>グラフ名
      <i class="acms-admin-icon-tooltip js-acms-tooltip" data-acms-tooltip="(必須項目)グラフ毎に固有なグラフ名を設定してください。"></i>
    </th>
    <td>
      <input type="text" name="chartid{id}" value="{chartid}" class="acms-admin-form-width-mini" placeholder="例)〇〇な円グラフ">
      <input type="hidden" name="unit{id}[]" value="chartid{id}">
    </td>
  </tr>
  <tr>
    <th>横幅
      <i class="acms-admin-icon-tooltip js-acms-tooltip" data-acms-tooltip="グラフの横幅をピクセル単位で設定します。"></i>
    </th>
    <td>
      <input type="text" name="chartwidth{id}" value="{chartwidth}" class="acms-admin-form-width-mini" placeholder="例)300">
      <input type="hidden" name="unit{id}[]" value="chartwidth{id}">
      <span>px</span>
    </td>
  </tr>
  <tr>
    <th>位置
      <i class="acms-admin-icon-tooltip js-acms-tooltip" data-acms-tooltip="グラフの位置を設定します。"></i>
    </th>
    <td>
      <select name="chart_margin{id}" class="acms-admin-form-width-mini">
          <option value="left" {chart_margin:selected#left}>左寄せ</option>
        <option value="center" {chart_margin:selected#center}>中央寄せ</option>
        <option value="right" {chart_margin:selected#right}>右寄せ</option>
      </select>
      <input type="hidden" name="unit{id}[]" value="chart_margin{id}">
    </td>
  </tr>
</table>
<table class="js-fieldgroup-sortable adminTable acms-admin-table-admin-edit">
  <thead class="acms-admin-hide-sp">
    <tr>
      <th class="acms-admin-table-left acms-admin-admin-config-table-item-handle">&nbsp;</th>
      <th class="acms-admin-table-left">ラベル
        <i class="acms-admin-icon-tooltip js-acms-tooltip" data-acms-tooltip="ラベル名を設定します。"></i>
      </th>
      <th class="acms-admin-table-left chart_color_bk-js">色
        <i class="acms-admin-icon-tooltip js-acms-tooltip" data-acms-tooltip="各グラフの色を設定します。"></i>
      </th>
      <th class="acms-admin-table-left">値
        <i class="acms-admin-icon-tooltip js-acms-tooltip" data-acms-tooltip="値を設定します。"></i>
      </th>
      <th class="acms-admin-table-left acms-admin-admin-config-table-action">削除</th>
    </tr>
  </thead>
  <tbody>
    <!-- BEGIN custom_chart:loop -->
    <tr class="sortable-item">
      <td class="item-handle">
        <i class="acms-admin-icon-sort"></i>
      </td>
      <td>
        <input type="text" name="chart_label{id}[]" value="{chart_label}" placeholder="例)ラベル" class="acms-admin-form-width-full">
      </td>
      <td class="chart_color_bk-js">
        <input type="color" name="chart_bk_color_single{id}[]" value="{chart_bk_color_single}" placeholder="例)#70a6fff" class="acms-admin-form-width-full chart_color_single-js">
      </td>
      <td>
        <input type="text" name="chart_data_single{id}[]" value="{chart_data_single}" placeholder="例)30" class="acms-admin-form-width-full chart_data_single-js">
      </td>
      <td>
        <input type="button" class="item-delete acms-admin-btn-admin acms-admin-btn-admin-danger" value="削除">
      </td>
    </tr>
    <!-- END custom_chart:loop -->
    <tr class="sortable-item item-template">
      <td class="item-handle">
        <i class="acms-admin-icon-sort"></i>
      </td>
      <td>
        <input type="text" name="chart_label{id}[]" value="" placeholder="例)ラベル" class="acms-admin-form-width-full">
      </td>
      <td class="chart_color_bk-js">
        <input type="color" name="chart_bk_color_single{id}[]" value="" placeholder="例)#c41134" value="#c41134" class="acms-admin-form-width-full chart_color_single-js">
      </td>
      <td>
        <input type="text" name="chart_data_single{id}[]" value="" placeholder="例)30" class="acms-admin-form-width-full chart_data_single-js">
      </td>
      <td>
        <input type="button" class="item-delete acms-admin-btn-admin acms-admin-btn-admin-danger" value="削除">
      </td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="5">
        <input type="button" class="item-insert acms-admin-btn-admin" value="追加">
      </td>
    </tr>
  </tfoot>
</table>
<input type="hidden" name="@custom_chart{id}[]" value="chart_label{id}">
<input type="hidden" name="unit{id}[]" value="chart_label{id}">
<input type="hidden" name="@custom_chart{id}[]" value="chart_border_color_single{id}">
<input type="hidden" name="unit{id}[]" value="chart_border_color_single{id}">
<input type="hidden" name="@custom_chart{id}[]" value="chart_bk_color_single{id}">
<input type="hidden" name="unit{id}[]" value="chart_bk_color_single{id}">
<input type="hidden" name="@custom_chart{id}[]" value="chart_data_single{id}">
<input type="hidden" name="unit{id}[]" value="chart_data_single{id}">
<input type="hidden" name="unit{id}[]" value="@custom_chart{id}">
<!-- END custom_chart -->

管理ページでの設定

管理ページ > コンフィグ > 編集設定 > ユニット追加ボタン に移動し、新しいユニットボタンを追加します。ユニット追加ボタンの [追加] をクリック、「モード」は 拡張 を選択し、上記のコード <!-- BEGIN custom_chart --> に書かれているものと同様の custom_chart と入力、「ラベル」は利用者に分かるようなラベルを設定します。今回の場合、グラフ か 円グラフ のように記述するといいでしょう。


ユニット追加ボタンの設定ができたら、管理ページ > コンフィグ > ユニット設定 を開いてください。ユニット設定の一番下に「グラフ」が増えていますので、[グラフ] ボタンをクリックしてください。そうする事で以下のようにグラフユニットが1つ追加されます。


ここまで設定すると、管理画面側の設定は完了になります。

表示側のテンプレートの実装

/themes/使用中のテーマ/include/unit/extend.html に下記ソースコードを追加してください。

<!-- BEGIN unit#custom_chart -->
<!-- BEGIN_SetRendered id="js-chart" -->
<script src="https://unpkg.com/in-view@0.6.1/dist/in-view.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<script>
$(function() {
  $('canvas').each(function() {
    var id = $(this).attr('id');
    var ctx = $(this).get(0).getContext('2d');
    var $template = $(this).next();
    var option = JSON.parse($template.html());
    inView('#'+ id).once('enter', function() {
      new Chart(ctx, option);
    });
  });
});
</script>
<!-- END_SetRendered -->
<div class="chart" style="<!-- BEGIN chartwidth:veil -->max-width: {chartwidth}px;<!-- END chartwidth:veil --><!-- BEGIN_IF [{chart_margin}/eq/center] --> margin: 0 auto 25px {chart_left};<!-- ELSE_IF [{chart_margin}/eq/left] --> margin: 0 auto 25px 0;<!-- ELSE_IF [{chart_margin}/eq/right] --> margin: 0 0 25px auto;<!-- END_IF -->">
  <canvas width="400" height="400" id="chart-{utid}"></canvas>
    <template data-id="chart-{utid}">
    {
      "type": "pie",
      "data": {
        "labels": [<!-- BEGIN custom_chart:loop --><!-- BEGIN glue -->,<!-- END glue -->"{chart_label}"<!-- END custom_chart:loop -->],
        "datasets": [{
          <!-- BEGIN chart_bk_color:veil -->"backgroundColor": [
          <!-- BEGIN custom_chart:loop --><!-- BEGIN glue -->,<!-- END glue -->"{chart_bk_color_single}"<!-- END custom_chart:loop -->
          ],<!-- END chart_bk_color:veil -->
          "data": [<!-- BEGIN custom_chart:loop --><!-- BEGIN glue -->,<!-- END glue -->{chart_data_single}<!-- END custom_chart:loop -->]
        }]
      }
    }
  </template>
  <p class="chart-name" style="text-align: center; margin-top: 5px;">{chartid}</p>
</div>
<!-- END unit#custom_chart -->

上記ソースコード3行目〜4行目では、グラフを描くための chart.js の読み込みと合わせて、表示されたタイミングでグラフが動くように inview.js も読み込んでいます。

次に、/themes/使用中テーマ/include/head/js.html に下記コードを追加してください。
※標準のテーマ(site2019/beginner2019/blog2019など)であれば js.html が内包されていますが、 js.html が無い場合は <head> タグ内に下記1行を追記してください。

<!-- GET_Rendered id="js-chart" -->

外部の JavaScript ライブラリを活用する際の最適な実装方法

今回は chart.js を読み込んでいるわけですが、<head> に使うか使わないか分からないのに毎回読み込んだり、複数のグラフユニットを追加した場合もユニットのループの中で追加したユニット分JavaScriptを読み込むのもいい実装とは言えません。

そこで、SetRendered を利用します。<head> に書く内容をユニットのループ内に書き、その部分を

<!-- BEGIN_SetRendered id="js-chart" -->

<!-- END_SetRendered -->

で囲む事によって、そこには表示させず変数化することができます。なのでカスタムユニットを複数個挿入したとしても、各ユニット内でJavaScriptが処理されるのではなく、<head> 内に書かれている

<!-- GET_Rendered id="js-chart" -->

SetRendered が展開されるため、JavaScriptの処理を1回だけにすることができます。このようにカスタムユニットで JavaScript を読み込む必要があるような場合には、SetRenderedGET_Rendered を活用してください。

「スライダーカスタムユニット」を作ってみよう

手順は説明しませんが、方法は上記の「グラフのカスタムユニット」と同様になります。

今後、JavaScript の読み込みが必要なカスタムユニットを表示する際には、SetRenderedGET_Rendered の利用をスタンダードな実装方法として活用ください。

同じタグ付けがされている記事