Chart.js 入門 - 美しいグラフを簡単に実装する方法

Chart.js 入門 - 美しいグラフを簡単に実装する方法

作成日:

Webサイトでデータを可視化したいとき、Chart.js は非常に強力な選択肢です。軽量でありながら美しいグラフを簡単に作成でき、レスポンシブ対応も標準で備えています。

この記事では、Chart.jsの基本的な使い方から、様々なチャートタイプの実装例まで、実践的なコードとともに解説します。


Chart.jsとは?

Chart.jsは、HTML5 Canvasを使用してグラフを描画するオープンソースのJavaScriptライブラリです。

特徴

  • 軽量: 圧縮版で約60KB程度
  • 8種類のチャートタイプ: 棒、折れ線、円、ドーナツ、レーダー、極座標、バブル、散布図
  • レスポンシブ対応: 画面サイズに合わせて自動リサイズ
  • アニメーション: デフォルトで滑らかなアニメーション
  • カスタマイズ性: 色、フォント、凡例、ツールチップなど細かく設定可能
  • プラグインエコシステム: データラベル、ズーム機能などの拡張

インストール方法

CDNから読み込む(最も簡単)

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

npmでインストール

Shell
npm install chart.js
JavaScript
import Chart from 'chart.js/auto';

基本構造

Chart.jsでグラフを作成する基本的な流れは以下の通りです:

  1. HTMLに <canvas> 要素を配置
  2. JavaScriptで new Chart() を呼び出し
  3. チャートタイプ、データ、オプションを設定
HTML
<canvas id="myChart"></canvas>
 
<script>
const ctx = document.getElementById('myChart');
 
new Chart(ctx, {
  type: 'チャートタイプ',
  data: {
    labels: ['ラベル1', 'ラベル2', '...'],
    datasets: [{
      label: 'データセット名',
      data: [値1, 値2, ...],
      // スタイリング設定
    }]
  },
  options: {
    // 表示オプション
  }
});
</script>

チャートタイプ別 実装例

1. 棒グラフ(Bar Chart)

最も基本的で使用頻度の高いチャートです。カテゴリ別のデータ比較に適しています。

HTML
<canvas id="barChart" width="400" height="200"></canvas>
 
<script>
const barCtx = document.getElementById('barChart');
 
new Chart(barCtx, {
  type: 'bar',
  data: {
    labels: ['1月', '2月', '3月', '4月', '5月', '6月'],
    datasets: [{
      label: '売上(万円)',
      data: [120, 190, 150, 180, 200, 220],
      backgroundColor: [
        'rgba(255, 99, 132, 0.7)',
        'rgba(54, 162, 235, 0.7)',
        'rgba(255, 206, 86, 0.7)',
        'rgba(75, 192, 192, 0.7)',
        'rgba(153, 102, 255, 0.7)',
        'rgba(255, 159, 64, 0.7)'
      ],
      borderColor: [
        'rgba(255, 99, 132, 1)',
        'rgba(54, 162, 235, 1)',
        'rgba(255, 206, 86, 1)',
        'rgba(75, 192, 192, 1)',
        'rgba(153, 102, 255, 1)',
        'rgba(255, 159, 64, 1)'
      ],
      borderWidth: 1
    }]
  },
  options: {
    responsive: true,
    scales: {
      y: {
        beginAtZero: true,
        title: {
          display: true,
          text: '売上(万円)'
        }
      }
    },
    plugins: {
      title: {
        display: true,
        text: '月別売上推移'
      }
    }
  }
});
</script>
棒グラフ デモ
読み込み中...
Loading...

横棒グラフ

type: 'bar' を使い、indexAxis: 'y' を設定します。

JavaScript
new Chart(ctx, {
  type: 'bar',
  data: data,
  options: {
    indexAxis: 'y',  // これで横棒グラフに
    responsive: true
  }
});
横棒グラフ デモ
読み込み中...
Loading...

2. 折れ線グラフ(Line Chart)

時系列データや連続したデータの推移を表現するのに最適です。

HTML
<canvas id="lineChart" width="400" height="200"></canvas>
 
<script>
const lineCtx = document.getElementById('lineChart');
 
new Chart(lineCtx, {
  type: 'line',
  data: {
    labels: ['1月', '2月', '3月', '4月', '5月', '6月'],
    datasets: [{
      label: '訪問者数',
      data: [1200, 1900, 3000, 2500, 4200, 5300],
      borderColor: 'rgba(75, 192, 192, 1)',
      backgroundColor: 'rgba(75, 192, 192, 0.2)',
      borderWidth: 2,
      fill: true,
      tension: 0.4  // 曲線の滑らかさ(0で直線)
    }, {
      label: 'コンバージョン',
      data: [100, 150, 280, 220, 380, 450],
      borderColor: 'rgba(255, 99, 132, 1)',
      backgroundColor: 'rgba(255, 99, 132, 0.2)',
      borderWidth: 2,
      fill: true,
      tension: 0.4
    }]
  },
  options: {
    responsive: true,
    plugins: {
      legend: {
        position: 'top',
      },
      title: {
        display: true,
        text: 'サイトアクセス推移'
      }
    },
    scales: {
      y: {
        beginAtZero: true
      }
    }
  }
});
</script>
折れ線グラフ デモ
読み込み中...
Loading...

ポイントスタイルのカスタマイズ

JavaScript
datasets: [{
  // ...
  pointStyle: 'circle',      // 'circle', 'cross', 'rect', 'star', 'triangle'
  pointRadius: 6,            // ポイントサイズ
  pointHoverRadius: 10,      // ホバー時のサイズ
  pointBackgroundColor: '#fff',
  pointBorderWidth: 2
}]

3. 円グラフ(Pie Chart)

全体に対する各要素の割合を表現します。

HTML
<canvas id="pieChart" width="300" height="300"></canvas>
 
<script>
const pieCtx = document.getElementById('pieChart');
 
new Chart(pieCtx, {
  type: 'pie',
  data: {
    labels: ['デスクトップ', 'モバイル', 'タブレット'],
    datasets: [{
      data: [55, 35, 10],
      backgroundColor: [
        'rgba(54, 162, 235, 0.8)',
        'rgba(255, 99, 132, 0.8)',
        'rgba(255, 206, 86, 0.8)'
      ],
      borderColor: [
        'rgba(54, 162, 235, 1)',
        'rgba(255, 99, 132, 1)',
        'rgba(255, 206, 86, 1)'
      ],
      borderWidth: 2,
      hoverOffset: 10  // ホバー時に飛び出す
    }]
  },
  options: {
    responsive: true,
    plugins: {
      legend: {
        position: 'bottom',
      },
      title: {
        display: true,
        text: 'デバイス別アクセス比率'
      },
      tooltip: {
        callbacks: {
          label: function(context) {
            return context.label + ': ' + context.raw + '%';
          }
        }
      }
    }
  }
});
</script>
円グラフ デモ
読み込み中...
Loading...

4. ドーナツグラフ(Doughnut Chart)

円グラフの中央を切り抜いたスタイル。中央に合計値や追加情報を表示できます。

HTML
<canvas id="doughnutChart" width="300" height="300"></canvas>
 
<script>
const doughnutCtx = document.getElementById('doughnutChart');
 
new Chart(doughnutCtx, {
  type: 'doughnut',
  data: {
    labels: ['完了', '進行中', '未着手', '保留'],
    datasets: [{
      data: [45, 30, 15, 10],
      backgroundColor: [
        'rgba(75, 192, 192, 0.8)',
        'rgba(54, 162, 235, 0.8)',
        'rgba(255, 206, 86, 0.8)',
        'rgba(201, 203, 207, 0.8)'
      ],
      borderWidth: 0
    }]
  },
  options: {
    responsive: true,
    cutout: '60%',  // 中央の穴のサイズ(デフォルト50%)
    plugins: {
      legend: {
        position: 'right',
      },
      title: {
        display: true,
        text: 'タスク進捗状況'
      }
    }
  }
});
</script>
ドーナツグラフ デモ
読み込み中...
Loading...

半円(ハーフドーナツ)を作る

JavaScript
options: {
  circumference: 180,   // 表示角度
  rotation: -90,        // 開始角度(-90で上から開始)
  cutout: '60%'
}
半円(ハーフドーナツ)デモ
読み込み中...
Loading...

5. レーダーチャート(Radar Chart)

複数の指標を同時に比較するのに適しています。スキル評価やプロダクト比較によく使われます。

HTML
<canvas id="radarChart" width="400" height="400"></canvas>
 
<script>
const radarCtx = document.getElementById('radarChart');
 
new Chart(radarCtx, {
  type: 'radar',
  data: {
    labels: ['JavaScript', 'TypeScript', 'React', 'Vue', 'Node.js', 'Python'],
    datasets: [{
      label: 'エンジニアA',
      data: [90, 85, 95, 70, 80, 60],
      backgroundColor: 'rgba(255, 99, 132, 0.2)',
      borderColor: 'rgba(255, 99, 132, 1)',
      borderWidth: 2,
      pointBackgroundColor: 'rgba(255, 99, 132, 1)'
    }, {
      label: 'エンジニアB',
      data: [75, 90, 70, 95, 85, 80],
      backgroundColor: 'rgba(54, 162, 235, 0.2)',
      borderColor: 'rgba(54, 162, 235, 1)',
      borderWidth: 2,
      pointBackgroundColor: 'rgba(54, 162, 235, 1)'
    }]
  },
  options: {
    responsive: true,
    scales: {
      r: {
        beginAtZero: true,
        max: 100,
        ticks: {
          stepSize: 20
        },
        pointLabels: {
          font: {
            size: 14
          }
        }
      }
    },
    plugins: {
      title: {
        display: true,
        text: 'スキル比較'
      }
    }
  }
});
</script>
レーダーチャート デモ
読み込み中...
Loading...

6. 極座標グラフ(Polar Area Chart)

円グラフと似ていますが、各セグメントの半径がデータ値を表します。

HTML
<canvas id="polarChart" width="300" height="300"></canvas>
 
<script>
const polarCtx = document.getElementById('polarChart');
 
new Chart(polarCtx, {
  type: 'polarArea',
  data: {
    labels: ['HTML/CSS', 'JavaScript', 'React', 'Node.js', 'Database'],
    datasets: [{
      data: [85, 90, 80, 70, 65],
      backgroundColor: [
        'rgba(255, 99, 132, 0.7)',
        'rgba(255, 206, 86, 0.7)',
        'rgba(54, 162, 235, 0.7)',
        'rgba(75, 192, 192, 0.7)',
        'rgba(153, 102, 255, 0.7)'
      ]
    }]
  },
  options: {
    responsive: true,
    scales: {
      r: {
        beginAtZero: true
      }
    },
    plugins: {
      legend: {
        position: 'bottom'
      },
      title: {
        display: true,
        text: '技術スキル分布'
      }
    }
  }
});
</script>
極座標グラフ デモ
読み込み中...
Loading...

7. 散布図(Scatter Chart)

2つの変数間の関係を視覚化します。相関関係の確認に便利です。

HTML
<canvas id="scatterChart" width="400" height="400"></canvas>
 
<script>
const scatterCtx = document.getElementById('scatterChart');
 
new Chart(scatterCtx, {
  type: 'scatter',
  data: {
    datasets: [{
      label: 'サンプルデータ',
      data: [
        { x: 10, y: 20 },
        { x: 15, y: 25 },
        { x: 20, y: 30 },
        { x: 25, y: 22 },
        { x: 30, y: 45 },
        { x: 35, y: 40 },
        { x: 40, y: 55 },
        { x: 45, y: 52 },
        { x: 50, y: 65 }
      ],
      backgroundColor: 'rgba(75, 192, 192, 0.8)',
      pointRadius: 8,
      pointHoverRadius: 12
    }]
  },
  options: {
    responsive: true,
    scales: {
      x: {
        title: {
          display: true,
          text: '広告費(万円)'
        }
      },
      y: {
        title: {
          display: true,
          text: '売上(万円)'
        }
      }
    },
    plugins: {
      title: {
        display: true,
        text: '広告費と売上の相関'
      }
    }
  }
});
</script>
散布図 デモ
読み込み中...
Loading...

8. バブルチャート(Bubble Chart)

散布図の各ポイントに「大きさ」という第3の次元を追加したチャートです。

HTML
<canvas id="bubbleChart" width="400" height="400"></canvas>
 
<script>
const bubbleCtx = document.getElementById('bubbleChart');
 
new Chart(bubbleCtx, {
  type: 'bubble',
  data: {
    datasets: [{
      label: '商品カテゴリ',
      data: [
        { x: 20, y: 30, r: 15 },  // r = バブルの半径
        { x: 40, y: 10, r: 10 },
        { x: 30, y: 22, r: 25 },
        { x: 50, y: 40, r: 20 },
        { x: 10, y: 50, r: 12 }
      ],
      backgroundColor: [
        'rgba(255, 99, 132, 0.7)',
        'rgba(54, 162, 235, 0.7)',
        'rgba(255, 206, 86, 0.7)',
        'rgba(75, 192, 192, 0.7)',
        'rgba(153, 102, 255, 0.7)'
      ]
    }]
  },
  options: {
    responsive: true,
    scales: {
      x: {
        title: {
          display: true,
          text: '価格帯'
        }
      },
      y: {
        title: {
          display: true,
          text: '販売数'
        }
      }
    },
    plugins: {
      title: {
        display: true,
        text: '商品分析(バブルサイズ = 利益率)'
      }
    }
  }
});
</script>
バブルチャート デモ
読み込み中...
Loading...

9. 複合チャート(Mixed Chart)

棒グラフと折れ線グラフなど、異なるタイプを組み合わせて表示できます。

私が実際に開発で使用したのもこのパターンで、エリアデータを棒グラフ、全国平均を折れ線グラフで表示しました。

HTML
<canvas id="mixedChart" width="400" height="200"></canvas>
 
<script>
const mixedCtx = document.getElementById('mixedChart');
 
new Chart(mixedCtx, {
  type: 'bar',  // ベースタイプ
  data: {
    labels: ['2018年', '2020年', '2022年', '2024年'],
    datasets: [
      {
        label: '東京都のエンジニア数',
        data: [280, 290, 300, 310],
        backgroundColor: 'rgba(0, 166, 81, 0.8)',  // ブランドカラー
        borderColor: 'rgba(0, 166, 81, 1)',
        borderWidth: 1,
        order: 2  // 描画順(大きいほど後ろ)
      },
      {
        type: 'line',  // このデータセットのみ折れ線
        label: '全国平均',
        data: [265.8, 265.8, 265.8, 265.8],
        borderColor: 'rgba(255, 152, 0, 1)',
        backgroundColor: 'transparent',
        borderWidth: 2,
        borderDash: [5, 5],  // 破線
        pointRadius: 0,
        fill: false,
        order: 1  // 前面に表示
      }
    ]
  },
  options: {
    responsive: true,
    maintainAspectRatio: true,
    scales: {
      y: {
        beginAtZero: false,
        min: 200,
        title: {
          display: true,
          text: '人口10万人あたり(人)'
        }
      }
    },
    plugins: {
      legend: {
        position: 'top'
      },
      title: {
        display: true,
        text: 'エンジニア数の推移と全国平均'
      },
      tooltip: {
        callbacks: {
          label: function(context) {
            return context.dataset.label + ': ' + context.raw + '';
          }
        }
      }
    }
  }
});
</script>
複合チャート デモ
読み込み中...
Loading...

共通オプション

レスポンシブ設定

JavaScript
options: {
  responsive: true,           // 画面サイズに合わせてリサイズ
  maintainAspectRatio: true,  // アスペクト比を維持
  aspectRatio: 2              // 幅:高さ = 2:1
}

アニメーション

JavaScript
options: {
  animation: {
    duration: 1000,           // アニメーション時間(ms)
    easing: 'easeOutQuart'    // イージング関数
  }
}
 
// アニメーション無効化
options: {
  animation: false
}

ツールチップ

JavaScript
options: {
  plugins: {
    tooltip: {
      enabled: true,
      backgroundColor: 'rgba(0, 0, 0, 0.8)',
      titleFont: { size: 14 },
      bodyFont: { size: 12 },
      padding: 12,
      callbacks: {
        label: function(context) {
          return context.dataset.label + ': ' + context.raw + '';
        }
      }
    }
  }
}

凡例(レジェンド)

JavaScript
options: {
  plugins: {
    legend: {
      display: true,
      position: 'top',        // 'top', 'bottom', 'left', 'right'
      align: 'center',
      labels: {
        boxWidth: 20,
        padding: 15,
        font: { size: 12 }
      }
    }
  }
}

実践Tips

1. データ属性から値を取得

HTMLのdata属性を使ってサーバーサイドからデータを渡すパターン。

HTML
<canvas id="chart"
        data-values="[120, 190, 150, 180]"
        data-labels='["1月", "2月", "3月", "4月"]'>
</canvas>
 
<script>
const canvas = document.getElementById('chart');
const values = JSON.parse(canvas.dataset.values);
const labels = JSON.parse(canvas.dataset.labels);
 
new Chart(canvas, {
  type: 'bar',
  data: {
    labels: labels,
    datasets: [{
      data: values
    }]
  }
});
</script>

2. 動的なデータ更新

JavaScript
const chart = new Chart(ctx, config);
 
// データ更新
chart.data.datasets[0].data = [新しいデータ];
chart.update();  // 再描画

3. グラフの破棄

SPAなどでコンポーネントをアンマウントする際は、メモリリークを防ぐためにグラフを破棄します。

JavaScript
chart.destroy();

まとめ

Chart.jsは、以下の点で優れたライブラリです:

  • 学習コストが低い: シンプルなAPIで素早く実装できる
  • 美しいデフォルトスタイル: そのままでも見栄えが良い
  • 柔軟なカスタマイズ: 細かい部分まで調整可能
  • レスポンシブ対応: モバイルでも適切に表示

データ可視化が必要なプロジェクトでは、まずChart.jsを検討してみてください。シンプルなグラフからやや複雑な複合チャートまで、幅広いニーズに対応できます。


参考リンク