レーダーチャートを表示する方法

Cocoonカスタマイズ集
この記事は約24分で読めます。
記事内に広告が含まれています。

完成イメージ

項目1
1
項目2
2
項目3
3

項目1
1
項目2
2
項目3
3
項目4
4

項目1
1
項目2
2
項目3
3
項目4
4
項目5
5

項目1
1
項目2
2
項目3
3
項目4
4
項目5
5
項目6
0

使用方法

以下にショートコードを示します。

[my_radar_chart label="項目1,項目2,項目3" score="1,2,3"]
オプション
オプション説明値初期値
label項目
score点数(必須)1~5、点数の数に応じ、3角形~6角形

実装手順

以下の手順で実装します。

  • ラベル
    PHPを追加

    以下のコードをfunctions.phpに追加します。

    add_shortcode('my_radar_chart', function ($atts) {
      $atts = shortcode_atts([
        'label' => '',
        'score' => ''
      ], $atts);
    
      $scores = explode(',', $atts['score']);
      $labels = array_map('trim', explode(',', $atts['label']));
    
      $max_shape = count($scores);
      if ($max_shape === 0) {
        return '';
      }
    
      $labels = array_pad($labels, $max_shape, '');
      $scores = array_map('intval', array_pad($scores, $max_shape, 0));
    
      $coordinates = [
        3 => [
          ["0 -20", "17.3 10", "-17.3 10"],
          ["0 -40", "34.6 20", "-34.6 20"],
          ["0 -60", "52 30", "-52 30"],
          ["0 -80", "69.3 40", "-69.3 40"],
          ["0 -100", "86.6 50", "-86.6 50"]
        ],
        4 => [
          ["0 -20", "20 0", "0 20", "-20 0"],
          ["0 -40", "40 0", "0 40", "-40 0"],
          ["0 -60", "60 0", "0 60", "-60 0"],
          ["0 -80", "80 0", "0 80", "-80 0"],
          ["0 -100", "100 0", "0 100", "-100 0"]
        ],
        5 => [
          ["0 -20", "19 -6.8", "11.8 16.2", "-11.8 16.2", "-19 -6.2"],
          ["0 -40", "38 -12.4", "23.5 32.4", "-23.5 32.7", "-38 -12.4"],
          ["0 -60", "57.1 -18.5", "35.3 48.5", "-35.3 48.5", "-57.1 -18.5"],
          ["0 -80", "76.1 -24.5", "47.6 64.7", "-47 64.7", "-76.1 -24.7"],
          ["0 -100", "95.2 -30.1", "58.8 80.9", "-58.8 80.9", "-95.2 -30.9"]
        ],
        6 => [
          ["0 -20", "17.3 -10", "17.3 10", "0 20", "-17.3 10", "-17.3 -10"],
          ["0 -40", "34.6 -20", "34.6 20", "0 40", "-34.6 20", "-34.6 -20"],
          ["0 -60", "52.0 -30", "52.0 30", "0 60", "-52.0 30", "-52.0 -30"],
          ["0 -80", "69.3 -40", "69.3 40", "0 80", "-69.3 40", "-69.3 -40"],
          ["0 -100", "86.6 -50", "86.6 50", "0 100", "-86.6 50", "-86.6 -50"]
        ]
      ];
    
      if (!isset($coordinates[$max_shape])) {
        $max_shape = 5;
      }
    
      $score_data = $coordinates[$max_shape];
      $points = [];
    
      foreach ($scores as $i => $score) {
        $level = max(-1, min($score - 1, 4));
        $points[] = ($level === -1) ? "0 0" : $score_data[$level][$i];
      }
    
      ob_start();
      $height = ($max_shape == 3) ? 160 : 210;
      ?>
      <div class="radar-chart radar-chart--<?= esc_attr($max_shape); ?>">
        <svg class="radar-chart__svg" xmlns="http://www.w3.org/2000/svg" viewBox="-100 -105 200 <?= $height ?>">
          <g class="radar-chart__grid" stroke="#e0e0e0">
            <?php foreach ($score_data[4] as $line): ?>
              <path d="M 0 0 L <?= $line ?>"/>
            <?php endforeach; ?>
          </g>
          <g class="radar-chart__shape" stroke="#e0e0e0" fill="none">
            <?php foreach ($score_data as $level): ?>
              <path d="M <?= implode(' L ', $level) ?> L <?= $level[0] ?>"/>
            <?php endforeach; ?>
          </g>
          <path d="M <?= implode(' L ', $points) ?> L <?= $points[0] ?>" class="radar-chart__area"/>
          <g class="radar-chart__points">
            <?php foreach ($points as $point):
              [$x, $y] = preg_split("/\s+/", $point);
            ?>
              <circle cx="<?= $x ?>" cy="<?= $y ?>" r="3"/>
            <?php endforeach; ?>
          </g>
        </svg>
        <dl class="radar-chart__labels">
          <?php foreach ($labels as $i => $t): ?>
            <div class="radar-chart__label">
              <dt><?= esc_html($t) ?></dt>
              <dd><?= esc_html($scores[$i]) ?></dd>
            </div>
          <?php endforeach; ?>
        </dl>
      </div>
      <?php
      return ob_get_clean();
    });
  • ラベル
    CSSを追加

    以下のコードをstyle.cssに追加します。

    .radar-chart {
      align-items: center;
      box-sizing: content-box;
      display: flex;
      height: 200px;
      justify-content: center;
      margin: 0 auto;
      padding: 35px;
      position: relative;
      width: 200px;
    
      .radar-chart__labels {
        height: 100%;
        position: absolute;
        width: 100%;
      }
    
      .radar-chart__label {
        position: absolute;
        text-align: center;
    
        dd {
          margin: 0;
        }
    
        /* 五角形 */
        &:nth-child(1) {
          left: 50%;
          top: 0;
          transform: translateX(-50%);
        }
    
        &:nth-child(2) {
          right: 10%;
          top: 33%;
          transform: translateX(50%);
        }
    
        &:nth-child(3) {
          bottom: -8%;
          right: 25%;
          transform: translateX(50%);
        }
    
        &:nth-child(4) {
          bottom: -8%;
          left: 25%;
          transform: translateX(-50%);
        }
    
        &:nth-child(5) {
          left: 10%;
          top: 33%;
          transform: translateX(-50%);
        }
      }
    
      .radar-chart__svg {
        height: 100%;
        width: 100%;
      }
    
      .radar-chart__area {
        fill: rgb(168 61 73 / 15%);
        stroke: #a83d49;
      }
    
      .radar-chart__points {
        fill: #a83d49;
      }
    
      /* 三角形 */
      &.radar-chart--3 {
        height: 160px;
    
        .radar-chart__label {
          &:nth-child(2) {
            bottom: 5%;
            right: 10%;
            top: unset;
          }
    
          &:nth-child(3) {
            bottom: 5px;
            left: 10%;
            right: unset;
            transform: translateX(-50%);
          }
        }
      }
    
      /* 四角形 */
      &.radar-chart--4 {
        margin-bottom: 2em;
    
        .radar-chart__label {
          &:nth-child(2) {
            right: 8%;
            top: 45%;
          }
    
          &:nth-child(3) {
            bottom: -14%;
            right: 50%;
          }
    
          &:nth-child(4) {
            left: 8%;
            top: 45%;
          }
        }
      }
    
      /* 六角形 */
      &.radar-chart--6 {
        .radar-chart__label {
          &:nth-child(3) {
            right: 10%;
            top: 66%;
            transform: translateX(50%);
          }
    
          &:nth-child(4) {
            bottom: -15%;
            left: 50%;
            transform: translateX(-50%);
          }
    
          &:nth-child(5) {
            top: 66%;
          }
    
          &:nth-child(6) {
            left: 10%;
            top: 33%;
            transform: translateX(-50%);
          }
        }
      }
    }
    
    .radar-chart__area,
    .radar-chart__points {
      transform: scale(0);
    }
    
    .radar-chart__area--animation,
    .radar-chart__points--animation {
      animation: radar-chart-scale 1s ease-out forwards;
    }
    
    @keyframes radar-chart-scale {
      0% {
        transform: scale(0);
      }
    
      100% {
        transform: scale(1);
      }
    }

レーダーチャートにアニメーションを追加する方法

前述のコードに加え、以下のコードを追加します。

  • ラベル
    JavaScriptを追加

    以下のコードを追加します。

    document.addEventListener("DOMContentLoaded", function () {
      // 監視対象となるすべての要素を取得
      var elms = document.querySelectorAll(".radar-chart");
    
      // 要素の状態を監視
      var observer = new IntersectionObserver(function (entries) {
        entries.forEach(function (entry) {
          if (entry.isIntersecting) {
            entry.target.querySelector(".radar-chart__points").classList.add("radar-chart__points--animation");
            entry.target.querySelector(".radar-chart__area").classList.add("radar-chart__area--animation");
    
            // 一度アニメーションした要素は監視対象から削除
            observer.unobserve(entry.target);
          }
        });
      }, { threshold: 0.5 });
    
      // 取得した各要素に対して監視を開始
      elms.forEach((elm) => observer.observe(elm));
    });
  • ラベル
    CSSを追加

    以下のコードをstyle.cssに追加します。

    .radar-chart__area,
    .radar-chart__points {
      transform: scale(0);
    }
    
    .radar-chart__area--animation,
    .radar-chart__points--animation {
      animation: radar-chart-scale 1s ease-out forwards;
    }
    
    @keyframes radar-chart-scale {
      0% {
        transform: scale(0);
      }
    
      100% {
        transform: scale(1);
      }
    }

「レーダーチャート」ブロックを活用する方法

「レーダーチャート」ブロックを活用します。
まず、「レーダーチャート」ブロックのみをあらかじめパターンとして登録しておきます。
その後、登録したパターンを独自のショートコードで呼び出し、項目や値を動的に変更してレーダーチャートを描画します。

使用方法

以下にショートコードを示します。

[my_radar_chart id=6 labels="項目1,項目2,項目3" scores="1,2,3"]
オプション
オプション説明値初期値
idパターンID(必須)
label項目(必須)
score点数(必須)1~5、点数の数に応じ、3角形~6角形

実装手順

以下のコードをfunctions.phpに追加します。

add_shortcode('my_radar_chart', function ($atts) {
  $atts = shortcode_atts([
    'id'    => '',
    'label' => '',
    'score' => '',
  ], $atts);

  wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);

  if (empty($atts['id']) || empty($atts['label']) || empty($atts['score'])) {
    return '<p>パラメータを正しく指定してください。</p>';
  }

  $reuse = get_post($atts['id']);
  if (! $reuse) {
    return '<p>指定されたパターンが見つかりません。</p>';
  }

  $content = $reuse->post_content;

  if (strpos($content, 'radar') === false) {
    return '<p>指定されたパターンはレーダーチャートではありません。</p>';
  }

  // idをユニークに変更
  if (preg_match('/id="(canvas-[a-zA-Z0-9_-]+)"/', $content, $m)) {
    $old_id = $m[1];
    $new_id = 'canvas-' . substr(md5(uniqid('', true)), 0, 8);
    $content = str_replace($old_id, $new_id, $content);
  }

  // ラベル・データを配列にしてJSONエンコード
  $labels_arr = array_map('trim', explode(',', $atts['label']));
  $scores_arr = array_map('intval', explode(',', $atts['score']));
  $labels_json = json_encode($labels_arr, JSON_UNESCAPED_UNICODE);
  $scores_json = json_encode($scores_arr);

  // データを置換
  $content = preg_replace('/labels:\s*\[[^\]]*\]/', "labels: $labels_json", $content);
  $content = preg_replace('/data:\s*\[[^\]]*\]/', "data: $scores_json", $content);

  return $content;
});

参考:Chart.jsを用いてレーダーチャートを表示する方法

「レーダーチャート」ブロックと同様に、ライブラリ「Chart.js」を使用して独自のショートコードで描画します。

実装方法

以下のコードをfunctions.phpに追加します。

add_shortcode('my_radar_chart', function ($atts) {
  $atts = shortcode_atts([
    'label' => '',
    'score' => '',
  ], $atts);

  wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);

  $labels = array_map('trim', explode(',', $atts['label']));
  $data   = array_map('trim', explode(',', $atts['score']));

  // ラベルに点数を追加
  $display_labels = [];
  foreach ($labels as $i => $label) {
    $val = isset($data[$i]) ? $data[$i] : 0;
    $display_labels[] = $label . " ( $val )";
  }

  // ユニークなIDを設定
  $chart_id = 'chart_radar_' . uniqid();

  ob_start();
  ?>
  <div class="my-radar-wrap">
    <canvas id="<?= esc_attr($chart_id); ?>" height="400"></canvas>
  </div>

  <script>
    document.addEventListener('DOMContentLoaded', function () {
      var canvas = document.getElementById('<?= esc_js($chart_id); ?>');
      if (! canvas) {
        return;
      }
      var ctx = canvas.getContext('2d');
      new Chart(ctx, {
        type: 'radar',
        data: {
          labels: <?= json_encode($display_labels); ?>,
          datasets: [{
            data: <?= json_encode($data); ?>,
            // 背景色
            backgroundColor: "rgba(44, 169, 225, 0.2)",
            // ボーダー色
            borderColor: "rgba(34, 202, 225, 0.9)",
            // ボーダーの太さ
            borderWidth: 1
          }]
        },
        options: {
          layout: {
            padding: { top: 30, bottom: 30, left: 30, right: 30 },
          },
          scales: {
            r: {
              max: 5,
              min: 0,
              ticks: {
                stepSize: 1,
                display: true,
                font: { size: 11, weight: 400 },
              },
              grid: {
                // グリッド線の色
                color: "rgba(221, 221, 221, 0.5)",
                display: true
              },
              angleLines: {
                display: true,
              },
              pointLabels: {
                font: { size: 11, weight: 400 },
              }
            }
          },
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: {
              display: false
            }
          }
        }
      });
    });
  </script>
  <?php
  return ob_get_clean();
});

さいごに

今回紹介した方法を使えば、簡単にWordPressでレーダーチャートを表示することができ、さらにアニメーションを追加することで視覚的にも魅力的なデザインを実現できます。
レーダーチャートを活用して、データの可視化を効果的に行いましょう。

タイトルとURLをコピーしました