sk

開発で得たこと

Chart.jsでおしゃれでかっこいいチャートを実装する

この記事で行うこと

チケットの予約情報をチャートで表示します。

f:id:sksksksksk:20180729181231p:plain
デモ Chart.js

使うもの

前提

以下を完了していること。

現場では?

管理画面でよくチャートが使われます。 Chart.jsは導入もシンプルですので人気なライブラリです。

難しいのはチャートに表示させるためのデータを取得する関数や処理です。

実装手順

Chart.jsのインストール

Gemfile

gem 'chart-js-rails'
bundle install

Javascriptを使うのでwebpackerを導入します。 Railsアプリにwebpackerの導入 - さがえもん を見て導入をしてください。

app/assets/javascripts/application.js

//= require bootstrap
//= require Chart.min # 追加
//= require_tree .

# 追加 の文字は削除してください。エラーが発生します。

チャートの表示

  • チケットの詳細ページを作成

詳細ページへのリンクを追加します。

app/views/tickets/index.html.haml

.col-xs-12
  %table.table
    %thead
      %tr
        ・・・
        %th # 追加
    %tbody
      - @tickets.each.with_index(1) do |ticket, index|
        %tr
          ・・・
          %td.text-center= link_to '詳細', ticket, class: 'btn btn-block' # 追加

showページに表示するticketを取得します。

app/controllers/tickets_controller.rb

  def show
    @ticket = Ticket.find(params[:id])
  end

チケット詳細ページの要素を追加します。

app/views/tickets/show.html.haml

.col-xs-12
  .page-header
    %h3 チケット概要
  %table.table
    %thead
      %tr
        %th チケット名
        %th 内容
        %th.text-center チケット販売可能枚数
        %th.text-center 締切日
    %tbody
      %tr
        %td= @ticket.title
        %td= @ticket.body
        %td.text-center= @ticket.number
        %td.text-center= @ticket.expired_at

  .page-header
    %h3 チケットデータ

f:id:sksksksksk:20180729154118p:plain

  • チャートを表示

app/views/tickets/show.html.haml

  .page-header
    %h3 チケットデータ
  -# 追加(開始位置)
  .ticket-show-chart-wrapper
    %canvas{ id: 'chart', width: '900', class: 'chart' }
= javascript_pack_tag 'ticket-show-chart'
-# 追加(終了位置)

グラフの拡大阻止 .ticket-show-chart-wrapper でラップしてあげることでグラフが拡大するのを避けられます。 グラフの描画点 canvasid: 'chart' がグラフの描画位置を示します。 ** jsの呼び出し javascript_pack_tag で対象のグラフを呼び出します。

レスポンシブ · Chart.js 日本語ドキュメント

呼び出すJSコードの設定です。 ajaxでサーバーと通信をしています。 通信対象のアクションはtickets#showです。

app/javascript/packs/ticket-show-chart.js

showScoreChart();

// 関数化
function showScoreChart() {
  $.ajax({
    type: 'GET',
    url: `/tickets/${$('.page-header').attr('ticket-id')}`,
    dataType: 'JSON',
    success: function(data) {
      // 描画位置の取得
      var context = document.getElementById('chart').getContext('2d');
      // 背景カラーの用意
      var graphColorArray = ['rgba(244, 143, 177, 0.6)', 'rgba(255, 235, 59, 0.6)'];
      // チャートデータの生成
      var myChart = new Chart(context, {
          // 円グラフを指定
          type: 'pie',
          data: {
            // チャート上部のラベル
            labels: data.gender_names,
            datasets:  [{
              data: data.genders,
              backgroundColor: graphColorArray, // グラフカラー
              pointBackgroundColor: '#ffffff' // 背景カラー
            }]
          },
          // チャートのオプション設定
          options: {
            responsive: true, // レスポンシブ設定
            maintainAspectRatio: false, // アスペクト比の維持設定
          }
      });
    }
  });
};

通信アクションのtickets#showを実装します。 formatを使って、htmlとjsonで返せるようにします。

app/controllers/tickets_controller.rb

  def show
    @ticket = Ticket.find(params[:id])
    respond_to do |format|
      format.html
      format.json do
        render json: {
          gender_names: Users::Profile.genders_i18n.invert.keys, # genderの属性名 ['男性', '女性']
          genders: @ticket.deliveries.genders
        }
      end
    end
  end

@ticket.deliveries.genders でそのチケットを予約している男女数を配列で取得します。

app/models/delivery.rb

  belongs_to :ticket
  # -------------------------------------------------------------------------------
  # ClassMethods
  # -------------------------------------------------------------------------------
  #
  # 男女数を配列で返す
  #
  # @return  ex. [10, 20]
  #
  def self.genders
    genders = []
    users = User.where(id: pluck(:user_id))
    Users::Profile.genders.keys.each { |gender| genders << Users::Profile.where(user: users, gender: gender.to_sym).count }
    genders
  end

最後にルーティングを設定して完了です。

config/routes.rb

resources :tickets, only: %i(new create index show)

動作確認

何人かユーザーを作成し、男女に分けてプロフィールを更新しておいてください。

男性グラフにカーソルを合わせると... f:id:sksksksksk:20180729181156p:plain 女性グラフにカーソルを合わせると... f:id:sksksksksk:20180729181231p:plain

参考

Chart.js | Open source HTML5 Charts for your website github.com Chart.js · Chart.js 日本語ドキュメント

ソースコード

github.com

質疑応答

コメントしてください。 こんなコード見たいというような要望あれば記事にしますのでそちらもコメントかメッセージください。

次のチュートリアル

www.sendai-freelance.com

ProgateやRailsチュートリアル、プログラミングスクールを通い終えたが現場のコードはかけない、

一体どうやって書くの?と思っているエンジニアのみなさんのためのチュートリアルを公開しています。

チュートリアル