【WordPress】Chart.jsでCanvas外にカスタムラベルをHTMLで配置する方法

Chart.jsでCanvas外にカスタムラベルをHTMLで配置する方法

Chart.jsでレーダーチャートを作る際、標準のラベル表示機能では日本語・英語の複数行表示やスタイル指定に限界があります。
そこで本記事では、ラベルをChart.jsのCanvas外にHTMLとして自由に配置し、デザインの自由度とSEO対応を両立する実装方法を紹介します。

目次

なぜChart.jsのラベルをHTMLで出力するのか?

Chart.jsはCanvasベースの描画ライブラリであり、ラベル(pointLabels)はCanvas内に直接描画されるため、以下のような制限があります。

  • 日本語と英語を行分けで表示できない
  • フォントや色などのスタイル指定が困難

これを解決するために、「ラベル部分だけHTMLで出力し、Canvasの外側に自由に配置」する方法を採用します。

実装イメージ

  • Canvas中央にChart.jsのレーダーチャートを表示
  • 6つの項目ラベルをCanvasの外にHTMLで配置
  • ラベルはACF(Advanced Custom Fields)で日本語+英語を管理
  • BEM命名規則でクラスを統一し、スタイル制御を明確化

実装手順

1. ACFで6項目のラベルと数値を用意

ACF無料版でも以下のようにグループで構成可能です。

フィールド名内容
chart_1 ~ 6グループ
└ label_ja日本語ラベル
└ label_en英語ラベル
└ value値:範囲(0〜100)
manager_colorチャートの色:カラーピッカー(16進値文字列)

ACF画面のスクショも貼っておきます。

ACF画面(ラベルの部分)
ACF画面(カラーの部分)

私は、カスタムタクソノミーに設定しています。
管理画面ではこのように表示されます。

2. JavaScriptとHTMLとPHPでラベルを出力

2-1. JavaScriptライブラリ(headタグなどに埋め込み)

Chart.jsを読み込みます。
この後のコードより先に読み込ませる必要があるため、headタグ内に書いた方がいいと思います。

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

2-2. JavaScriptとHTMLとPHP(bodyタグ内に埋め込み)

次のコードをbodyタグ内に埋め込みます。
JavaScriptとHTMLとPHPが混在していますが、この順番ではないとうまく出力されません。
構成は以下のようになっています。

  1. 【PHP】ACFに入っている値を取得
  2. 【JavaScript】PHPからJavaScriptにデータを渡す
  3. 【HTML,PHP】チャートの出力コードを書く
  4. 【JavaScript】チャートの出力コードを書く
<?php
// 1. ACFに入っている値を取得----
$charts = [];

for ($i = 1; $i <= 6; $i++) {
	$group = get_field("chart_$i"); // チャートのグループフィールドを取得
	$label_ja = $group['label_ja'] ?? ''; // 日本語ラベル
	$label_en = $group['label_en'] ?? ''; // 英語ラベル
	$value = $group['value'] ?? 0; // チャートの値

	$charts[] = [
		'label_ja' => $label_ja,
		'label_en' => $label_en,
		'value' => $value
	];
}

$values = array_column($charts, 'value'); // チャートの値を配列に格納
$color = get_field('manager_color'); // 色を取得
?>


<script>
	// 2.PHPからJavaScriptにデータを渡す----
	const chartData = {
		values: <?php echo json_encode(array_column($charts, 'value')); ?>,
		color: <?php echo json_encode(get_field('manager_color')); ?>
	};
</script>


<!-- 3.チャートの出力コード -->
<div class="p-radarChart">
	<?php foreach ($charts as $index => $item): ?>
		<div class="p-radarChart__label p-radarChart__label--<?php echo $index; ?>">
			<span class="en"><?php echo esc_html($item['label_en']); ?></span>
			<strong class="ja"><?php echo esc_html($item['label_ja']); ?></strong>
		</div>
	<?php endforeach; ?>
	<canvas id="p-radarChart__canvas" class="p-radarChart__canvas" width="400" height="400"></canvas>
</div>


<script>
// 4.チャートの出力コード----
// HEX → RGBA変換関数(背景に透明度をつけるため)
	function hexToRgba(hex, alpha = 1) {
		const r = parseInt(hex.slice(1, 3), 16);
		const g = parseInt(hex.slice(3, 5), 16);
		const b = parseInt(hex.slice(5, 7), 16);
		return `rgba(${r}, ${g}, ${b}, ${alpha})`;
	}

	// チャート初期化
	const ctx = document.getElementById('p-radarChart__canvas').getContext('2d');

	new Chart(ctx, {
		type: 'radar',
		data: {
			labels: ['', '', '', '', '', ''], // Canvas内のラベルは非表示
			datasets: [{
				label: 'Player Stats',
				data: chartData.values,
				fill: true,
				backgroundColor: hexToRgba(chartData.color, 0.6), // 60%透明
				borderColor: chartData.color, // 枠線の色
				pointBackgroundColor: 'transparent', //頂点の色
				borderWidth: 0, // 枠線の太さ
			}]
		},
		options: {
			responsive: false,
			scales: {
				r: {
					min: 0,
					max: 100,
					pointLabels: {
						display: false
					},
					ticks: {
						display: false
					},
					grid: {
						color: '#ccc'
					},
					angleLines: {
						color: '#ccc'
					}
				}
			},
			plugins: {
				legend: {
					display: false
				}
			}
		}
	});
</script>

2-3. SCSSで装飾

/*レーダーチャート--------*/
.p-radarChart {
  position: relative;
  width: 400px;
  height: 400px;
  margin: 0 auto;

  &__canvas {
    width: 100%;
    height: 100%;
    display: block;
  }

  &__label {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    text-align: left;
    font-size: 14px;
    line-height: 1.4;
    color: #333;
    transform: translate(-50%, -50%);
    white-space: nowrap; /* 改行を防止 */
    pointer-events: none;

    .en {
      display: block;
      color: #666;
      font-size: 12px;
      text-transform: uppercase; // 英語のテキストを大文字に変換
    }
    .ja {
      display: block;
      font-size: 14px;
    }

    /* ラベル配置 */
    &--0 {
      top: -5%;
      left: 50%;
    }
    &--1 {
      top: 21%;
      left: 100%;
    }
    &--2 {
      top: 78%;
      left: 100%;
    }
    &--3 {
      top: 105%;
      left: 50%;
    }
    &--4 {
      top: 78%;
      left: 0%;
    }
    &--5 {
      top: 21%;
      left: 0%;
    }
  }
}
Chart.jsでCanvas外にカスタムラベルをHTMLで配置する方法

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
目次