iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
JavaScript

PM說: RD大大,這個功能要怎麼寫啊?系列 第 5

PM 說: 客戶要做出"反向雷達圖" Σ ヽ(゚ Д ゚; )ノ

  • 分享至 

  • xImage
  •  

雷達圖example
source

前言

雷達圖是我們日常生活蠻常看到的一種圖表~

某天...
PM: RD 大大網頁的雷達圖會很難做嗎?
我: 不會呀,有很多現成的套件改改參數就能實現
PM: 那反向雷達圖?
我: 反向?!
PM: 對,最外圈是 0;最內圈是 100;然後要圓形的
我: 好...我努力研究

成果

先實現一版正常的圓形雷達圖
正常的圓形雷達圖範例
正向

再實現反向的圓形雷達圖
反向的範例
反向

如果有更好的方式再麻煩各位開發者留言告知我~感恩

程式碼

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>反向雷達圖範例</title>
  </head>
  <body>
    <!-- chart.jsv4.4 -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <div class="chart" style="height: 500px; width: 500px">
      <canvas id="chart"></canvas>
    </div>
    <div style="position: fixed; top: 0">
      ⚔️:50<br />
      ❤️:80<br />
      🏃 :60<br />
      🛡️ :50<br />
    </div>

    <script>
      window.onload = () => {
        const ctx = document.getElementById("chart");
        const blue = "#ADD8E6";
        const color = Chart.helpers.color;
        const lightBlue = color(blue).alpha(0.2).rgbString();
        const config = {
          type: "radar",
          data: {
            labels: [
              ["⚔️", "attack"],
              ["❤️", "vital"],
              ["🏃", "speed"],
              ["🛡️", "defend"],
            ],
            datasets: [
              {
                label: "",
                backgroundColor: lightBlue,
                borderColor: lightBlue,
                pointBackgroundColor: blue,
                data: [100 - 50, 100 - 80, 100 - 60, 100 - 50], // 要反向同 callback
              },
            ],
          },
          options: {
            // 自動稱滿寬度
            maintainAspectRatio: false,
            // 隱藏 "legend" 或 "圖例"
            plugins: {
              legend: {
                display: false,
              },
              tooltip: {
                callbacks: {
                  label: (context) => {
                    const originalValue = context.raw;
                    const reversedValue = 100 - originalValue;
                    return `${context.dataset.label || ""}: ${reversedValue}`;
                  },
                },
              },
            },
            scales: {
              r: {
                grid: {
                  circular: true, // 雷達圖外框=圓形
                },
                beginAtZero: true, // 最外圈從0開始
                min: 0, //外框數字最小=0
                max: 100, //內框數字最大=100
                // 每圈的間隔
                ticks: {
                  min: 0,
                  max: 100,
                  stepSize: 25,
                  // 內部框和點回傳值
                  callback: (value, index, values) => {
                    return 100 - value;
                  },
                },
              },
            },
          },
        };
        new Chart(ctx, config);
      };
    </script>
  </body>
</html>

重點

因為最大值是 100; 故反向就是 100 - n

  1. datasets 資料要反向

  2. tooltip 顯示的文字要反向

文件:
https://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-callbacks

// 可以針對 label 回傳做客製化
              tooltip: {
                callbacks: {
                  label: (context) => {
                    const originalValue = context.raw;
                    const reversedValue = 100 - originalValue;
                    return `${context.dataset.label || ""}: ${reversedValue}`;
                  },
                },
              },
  1. ticks 間隔要反向
    文件:
    https://www.chartjs.org/docs/latest/axes/radial/linear.html#common-tick-options-to-all-axes
                // 每圈的間隔
                ticks: {
                  min: 0,
                  max: 100,
                  stepSize: 25,
                  // 內部框和點回傳值
                  callback: (value, index, values) => {
                    return 100 - value;
                  },
                },

後記

其實這個需求的 tooltip 是問 chatGPT 才知道能這樣使用 callback
否則面對 chartjs 這種設定檔非常多的庫
要實現特定需求非常費力~

若讀者有遇到這麼特別的需求,希望這篇有幫助到你(記得回來留言讓我知道)


上一篇
PM 說: 要怎麼寫外送平台的移動地圖抓地址?
下一篇
PM 說: 要怎麼寫出客製化window視窗來比對資料?
系列文
PM說: RD大大,這個功能要怎麼寫啊?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言