🏐

【chart.js】バレーボールの得点割合アプリを作る01

に公開

バレーボールに関するアプリを作りたい!

バレーボールネーションズリーグ盛り上がってますね。この記事を書いている時はVNL2025千葉ラウンドが開催しています。私は高校生の頃地上波で見た西田有志選手のプレーをきっかけにバレーボールにハマりました。卒論で作っているウェブアプリがあまり興味があるものではなく、「もっと好きなものを作りたい!」と思い、このアプリを作り始めました。

この記事ではchart.jsによるグラフ表示のやり方をメインとしプログラム全体の現状を軽くまとめます。

結論

chart.jsで得点割合を表示できるようになりました。

開発環境

  • windows10
  • Vscode

ファイル構造

volleyball-app/
├── index.html         # HTMLのエントリポイント
├── style.css          # 全体のスタイル
├── js/
│   ├── main.js        # 初期化処理・イベントの定義
│   ├── chart.js       # チャート描画処理
│   └── point.js       # スコア管理のロジック

事前準備

vscodeにはライブサーバーのプラグインが入っています。

やったこと

雛形コードの作成

htmlを作成しました。得点表を意識してポイントを表示するための要素と、どのプレーで得点したかを入力できるbutton要素を配置しました。

得点したチームのボタンをクリックしてどのプレーで得点したかをクリックします。そうすることで得点表が更新されます。例えば、Aがサーブで得点したら、A -> serverのようにクリックすることで値が更新されます。

次にjsを書きました。得点の操作はpoint.jsにまとめてmain.jsでイベントリスナーを登録することで使用しています。

チームが得点したときの加点処理とプレーの内容を追加する処理、それらをundoする処理を書きました。

次にすべての得点に対してどのプレーで得点したかの割合を示すパイチャート(円グラフ)を表示します。そのためにchart.jsを使用します。

chart.jsの使い方

htmlにchart.jsのcdnを読み込む行を書きます。

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

そして実際にパイチャートを表示するhtml要素を追加します。ここにチャートが表示されます。

<canvas id="myChart"></canvas>

ここから詳しいjsを書いていきます。チャートはnew Chart()で作ります。これは第1引数に先ほどのcanvas要素を受け取り、第2引数にグラフの詳細を示すデータを受け取ります。

const ctx = document.getElementById('myChart');

let chart = new Chart(ctx, {
    type: 'pie',
    data: {
      labels: labels,
      datasets: [{
          backgroundColor: colors,
          data: data
      }]
    },
    options: {}
  });

グラフの詳細データ

パイチャートの書き方です。その他のチャートは最後に示した参考文献や公式ドキュメントを確認して下さい。

type, data, optionsの3つを指定します。typeはチャートの種類を指定します。datalabelsでデータのラベルを、datasetsでラベルごとの実際の数値と色を指定します。optionsでは各種さまざまな設定ができます。詳しくは公式ドキュメントなどを確認してください。

チャートの大きさの調節ですが、optionで以下を指定してcssで調節します。

responsive: false,
maintainAspectRatio: false

実際に書いたコードを以下に示します。

import { getPoint } from "./point.js";

let chart;

const predata = [5,13,4,1,1,1];

const labels = ["serve", "spike", "block", "block-out", "miss", "other"];
const colors = [
    'rgba(255, 99, 132, 0.6)',   // serve
    'rgba(54, 162, 235, 0.6)',   // spike
    'rgba(255, 206, 86, 0.6)',   // block
    'rgba(75, 192, 192, 0.6)',   // block-out
    'rgba(153, 102, 255, 0.6)',  // miss
    'rgba(154, 140, 140, 0.6)'    // other
  ];

export function showChart(canvas_html) {
    const point = getPoint();
    chart = new Chart(canvas_html,{
        type: 'pie',
        data: {
        labels: labels,
        datasets: [{
            backgroundColor: colors,
            data: getData(point, "A")
        }]
        },
        options: {
            title: {
                display: true,
                text: 'point'
            },
            responsive: false,
            maintainAspectRatio: false
        }
    });
}

export function getData(point, team) {
    //[serve, spike, block, block-out, miss, other]

    let score = {
        "serve": 0,
        "spike": 0,
        "block": 0,
        "block-out": 0,
        "miss": 0,
        "other": 0
    }

    point[team]["scoreBy"].forEach(element => {
        if (score.hasOwnProperty(element)) {
            score[element] += 1;
        }
        if(element==="serve-miss" || element==="spike-miss") {
            score["miss"] += 1; 
        }
    });

    return Object.values(score);
}

まとめ

チャートの大きさの調整が一番大変でした。chatGPTなどに聞きながら、解決しました。Chart.jsではもっと複雑な設定ができるっぽいので試してみようと思います。

雛形としては現状良いと考えていますが、選手ごとのデータも可視化したいので、どうやってやろうかと試行錯誤中です。

ではまた

01:ここ
02:執筆中

参考文献など

  • 公式ドキュメント

https://www.chartjs.org/docs/latest/getting-started/

https://qiita.com/Haruka-Ogawa/items/59facd24f2a8bdb6d369

Discussion