新視野行銷企劃

Chart.js 實作互動圖表的範例

扁平化設計的網頁封面圖,展示 Chart.js 實作互動圖表的範例,包含折線圖與長條圖,配有游標指向資料點,象徵互動與資料視覺化應用。

引言

當您在教育場域中需要將抽象的數據轉化為生動的視覺資訊時,一個好的圖表可以發揮巨大的作用。Chart.js 是一款簡單而靈活的開源 JavaScript 圖表庫,它利用 HTML5 <canvas> 元素,讓開發者能夠輕鬆地在網頁中加入具有互動性的圖表。對於具備中階前端技能的教育工作者或開發者而言,Chart.js 提供了快速將數據可視化的途徑。例如,教師可以使用互動圖表即時展示統計結果,學生則能透過滑鼠懸停或點擊與圖表互動,以更直觀地理解數據背後的含義。

本教學文章將以淺顯易懂的方式,引導您逐步實作數種常見的圖表類型,包括折線圖、長條圖和圓餅圖,並說明如何在純 HTML 與 JavaScript 的環境下(不依賴任何框架)使用 Chart.js 來製作這些圖表。我們將著重介紹 Chart.js 的基本設定方法,展示圖表預設的互動性功能(如提示框和圖例切換),並進一步講解如何透過事件監聽和資料更新來實現更豐富的互動效果。此外,在文章後半部分,我們還會針對 Chart.js 初學者常見的問題進行問答整理,幫助您避開初次使用時可能遇到的疑惑。透過本篇教學,您將能夠掌握 Chart.js 的核心用法,在教育情境中創建引人入勝的互動圖表。

折線圖(Line Chart)範例

折線圖常用於呈現資料隨時間或連續序列的變化趨勢。在教育情境下,您可以利用折線圖來顯示例如學生的成績隨學期進展的走勢,或某項活動每月參與人數的增減情況。現在,我們以一個簡單的範例來說明如何使用 Chart.js 繪製折線圖。

首先,確保 HTML 中已經透過 CDN 引入了 Chart.js,並放置了一個帶有唯一 ID(例如 "lineChart")的 <canvas> 元素作為繪圖容器。接著,我們可以在一段 <script> 中初始化並繪製折線圖:

HTML / JavaScript
<canvas id="lineChart"></canvas>
<script>
  const ctx = document.getElementById('lineChart').getContext('2d');
  new Chart(ctx, {
    type: 'line',
    data: {
      labels: ['1月','2月','3月','4月','5月','6月'],  // X軸標籤(例如月份)
      datasets: [{
        label: '平均成績',                 // 資料集名稱
        data: [50, 55, 60, 58, 64, 70],    // 對應各月份的數值
        borderColor: 'rgba(75, 192, 192, 1)',  // 折線顏色
        backgroundColor: 'rgba(75, 192, 192, 0.2)', // 區域填充顏色(透明度0.2)
        fill: true,                       // 是否填滿折線下方區域
        tension: 0.3                      // 平滑曲線的張力設置(0為直線)
      }]
    },
    options: {
      scales: {
        y: {
          beginAtZero: true               // Y軸從0開始繪製
        }
      }
    }
  });
</script>

上述程式碼將在畫布元素上繪製一條折線圖。labels 陣列定義了 X 軸的刻度(這裡使用1月至6月表示一年的前六個月),而 data 陣列則提供對應每個月份的數值。Chart.js 自動會根據這些數據繪製出折線,並在圖表兩側生成相應的座標軸。我們為資料集設定了 label: "平均成績",因此圖表上方會出現一個圖例標示出這條線代表的意義(平均成績)。borderColor 和 backgroundColor 用於自訂線條和填充區域的顏色,在此我們選擇了帶有透明度的青綠色,使圖表看起來更醒目又不至於遮蔽其他內容。fill: true 表示繪製折線時填滿下方區域,如果您只想要線條而不填色,可以將其設為 false。tension: 0.3 則讓折線呈現略為平滑的曲線,數值越接近0則線條越筆直。

在 options 中,我們啟用了 beginAtZero: true,確保 Y 軸從0開始繪製,以便在數值範圍較高時,圖表的起點不會懸空。完成上述設定後,圖表會自動按照提供的資料進行渲染。將滑鼠移動到折線上的資料點時,Chart.js 會自動顯示該點的詳細數值(稱為 tooltip 的提示框)。由於我們定義了資料集的 label,圖例也會顯示在圖表上方,使用者可以透過點擊圖例來切換資料集的顯示與隱藏(在本例中只有一條資料線,點擊圖例可暫時移除或重新顯示這條線)。這些互動功能都是 Chart.js 預設提供的,開發者無需額外撰寫代碼就能享受到基本的互動效果。

長條圖(Bar Chart)範例

長條圖適合用來比較不同類別之間的數值高低。例如,教師可以將不同科目的平均成績以長條圖呈現,一目了然地比較哪一科表現最佳;或者統計不同班級的人數差異等。在這個範例中,我們將示範如何使用 Chart.js 繪製一個簡單的長條圖。

與前述折線圖的步驟類似,您需要在 HTML 中建立一個 <canvas id="barChart"> 作為長條圖的容器,並確保已引入 Chart.js。然後,我們使用以下的程式碼來產生長條圖:

HTML / JavaScript
<canvas id="barChart"></canvas>
<script>
  const ctx2 = document.getElementById('barChart').getContext('2d');
  new Chart(ctx2, {
    type: 'bar',
    data: {
      labels: ['數學','自然','歷史','語文','藝術'], // X軸分類標籤
      datasets: [{
        label: '平均分數',
        data: [90, 85, 78, 88, 95],               // 每個科目的平均分
        backgroundColor: [
          '#42a5f5',
          '#66bb6a',
          '#ffa726',
          '#ab47bc',
          '#f44336'
        ],                                        // 各長條的填充顏色
        borderColor: [
          '#42a5f5',
          '#66bb6a',
          '#ffa726',
          '#ab47bc',
          '#f44336'
        ],                                        // 各長條的邊框顏色
        borderWidth: 1                           // 邊框寬度(1像素)
      }]
    },
    options: {
      scales: {
        y: {
          beginAtZero: true                      // 確保Y軸從0開始
        }
      }
    }
  });
</script>

在這個長條圖中,labels 陣列列出了五個科目,Chart.js 會在 X 軸上將它們依序展示。我們提供了一組對應的 data 數值(例如這些科目的平均分數)。每個數值將繪製成一根直立的長條柱,高度對應其數值大小。由於我們將 beginAtZero 設為 true,Y 軸從0開始,確保各科目的長條高度比例能被正確反映(若不從0開始,90分與95分的差異可能在視覺上被放大或縮小,不利於真實比較)。

我們使用 backgroundColor 提供了一個色彩陣列,為每個長條指定不同的顏色,使圖表更加美觀易讀。相應地,也設定了 borderColor 來為每個長條繪製邊框(預設邊框為細線,透過 borderWidth: 1 來控制其粗細)。如果您希望所有長條使用相同顏色,也可以將 backgroundColor 設為一個單一的色碼字串(如 backgroundColor: 'steelblue'),Chart.js 將自動套用該色碼至每個長條。

和折線圖一樣,長條圖在繪製完成後自帶互動效果:將滑鼠移動到任一長條上時,會自動出現該類別的名稱與具體數值的提示框,方便使用者閱讀精確資料。圖例部分由於我們提供了資料集的 label: "平均分數",因此圖表上方會標示此資料系列的名稱。即使在只有一組資料的情況下,點擊圖例也能暫時切換長條的顯示(當前資料集會被隱藏,再次點擊則恢復顯示)。這種互動讓讀者可以自行選擇關注或排除某些數據系列(在單一數據集的情況下意義不大,但在多組資料比較時非常實用)。

圓餅圖(Pie Chart)範例

圓餅圖用於表現整體中各部分所佔的比例,非常適合展示組成結構。例如,教師可以用圓餅圖來顯示班級中不同等第的人數比例,或者說明學生一天當中分配在各種活動上的時間佔比。透過圓餅圖,讀者可以直觀地看到各部分所佔百分比大小。

在開始繪製圓餅圖前,我們同樣需要一個 <canvas id="pieChart"> 來承載圖表,並保證 Chart.js 庫已正確載入。以下是產生圓餅圖的程式碼:

HTML / JavaScript
<canvas id="pieChart"></canvas>
<script>
  const ctx3 = document.getElementById('pieChart').getContext('2d');
  new Chart(ctx3, {
    type: 'pie',
    data: {
      labels: ['學習', '睡眠', '運動', '娛樂'],
      datasets: [{
        data: [8, 8, 2, 6],
        backgroundColor: [
          'rgba(255, 99, 132, 0.8)',
          'rgba(54, 162, 235, 0.8)',
          'rgba(255, 206, 86, 0.8)',
          'rgba(75, 192, 192, 0.8)'
        ],
        borderColor: ['#ffffff', '#ffffff', '#ffffff', '#ffffff'],
        borderWidth: 2
      }]
    },
    options: {
      plugins: {
        title: {
          display: true,
          text: '每日時間分配'
        },
        legend: {
          position: 'bottom'
        }
      }
    }
  });
</script>

以上的資料模擬了一位學生一天中學習、睡眠、運動、娛樂這四種活動所花費的小時數(共計24小時)。Chart.js 會將 data 陣列中的數值轉換為圓餅圖中扇區的角度,數值較大的部分會對應較大的扇區。labels 列表定義了每個扇區的名稱,這些名稱會顯示在圖例上,並以對應的顏色標示每個區塊。我們提供了 backgroundColor 陣列為每個扇區指定了顏色(使用帶透明度的顏色,使圖表色塊鮮明卻不刺眼),同時以 borderColor: '#ffffff' 和 borderWidth: 2 為每個扇區添加白色邊框,讓相鄰的區塊更容易區分。

在這個例子中,我們也示範了如何自訂圖表的標題和圖例位置:options.plugins.title 設定為 display: true 並給予文字 "每日時間分配",因此圖表上方會顯示出這個標題;options.plugins.legend.position: 'bottom' 則將圖例移至圖表下方列出,避免與標題產生擁擠。當圖表繪製完成後,讀者可以透過圖例查看各顏色所代表的活動類別,也可以將滑鼠移動到任一扇區上以查看該部分對應的實際數值(tooltip 會顯示例如 "睡眠: 8",表示睡眠佔了8小時)。和先前類似,點擊圖例中的項目可以切換對應扇區的顯示——這意味著使用者可以選擇暫時從圓餅圖中移除某一部分以強調其餘部分的比例。透過這種互動方式,圓餅圖能夠更靈活地用於講解資料,讓學生自主探索每一部分的意義。

圖表互動與動態更新

Chart.js 雖然預設提供了滑鼠懸停顯示資訊和點擊圖例切換數據等互動機制,但有時我們希望進一步與圖表互動,例如點擊圖表中的某個元素觸發自訂的動作,或即時更新圖表的資料。以下將介紹如何透過事件監聽和資料更新來強化圖表的互動性。

事件監聽:捕捉使用者點擊

假設我們希望使用者點擊某個圖表的元素(例如長條圖的一根柱子或折線圖上的一個點)時,能夠取得該項目的詳細資訊甚至觸發特定行為。我們可以利用 Chart.js 提供的事件回呼函式來達成這點。在圖表的 options 設定中,加上 onClick 屬性即可監聽使用者的點擊事件。以下範例展示如何設定 onClick 回呼:

JavaScript
options: {
  onClick: (event, elements) => {
    if (elements.length > 0) {
      // 取得被點擊的元素索引
      const { datasetIndex, index } = elements[0];
      const chart = event.chart;
      // 使用索引從圖表資料中取出標籤與數值
      const label = chart.data.labels[index];
      const value = chart.data.datasets[datasetIndex].data[index];
      alert(`您點擊了「${label}」,數值為 ${value}`);
    }
  },
  // ... 其他設定 (如 plugins, scales)
}

在上述程式碼中,onClick 回呼會在使用者每次點擊圖表時被調用。函式提供兩個參數:event(包含滑鼠事件和圖表本身等資訊)以及 elements(一個陣列,包含了被點擊處對應的圖表元素)。我們首先檢查 elements.length 是否大於0,以確定點擊是否命中了一個圖表上的資料點。如果有命中,我們從 elements[0] 中解構出被點擊元素所屬的資料集索引 (datasetIndex) 和該資料在陣列中的索引 (index)。接著,透過 event.chart 取得圖表實例,方便我們訪問其資料。利用這兩個索引,我們就能從 chart.data.labels 和 chart.data.datasets 中拿到對應的標籤及數值。此範例中,我們使用 alert 彈出一個訊息,告知使用者所點擊項目的名稱和數值。您也可以將這段程式碼改為其他行為,例如在網頁上顯示詳細資訊區塊,或記錄使用者的操作日誌。設定完 onClick 後,只要重新建立圖表或使用 chart.update() 套用更改,Chart.js 就會在偵測到使用者點擊資料項目時執行您定義的函式邏輯。

資料更新:即時修改圖表

在教育應用中,我們常常需要即時更新圖表以反映最新的資料,例如每隔幾秒鐘更新一次感測數據,或者根據使用者的輸入動態改變圖表內容。Chart.js 提供了友善的方式來更新圖表,而不必重新載入整個圖表對象。

要更新圖表資料,我們可以直接操作圖表實例的 data 屬性,然後呼叫一次 chart.update(),圖表就會重新渲染並呈現新的資料。以下舉幾個常見的資料更新操作:

JavaScript
// 假設我們有一個現有的圖表實例 myChart

// 1. 新增一筆資料(例如新增一個類別及其數值)
myChart.data.labels.push('新項目');
myChart.data.datasets[0].data.push(75);
myChart.update();

// 2. 更新現有的資料值(例如修改第一筆資料的值)
myChart.data.datasets[0].data[0] = 95;
myChart.update();

// 3. 移除最後一筆資料
myChart.data.labels.pop();
myChart.data.datasets[0].data.pop();
myChart.update();

以上程式碼片段示範了幾種情境:首先,我們使用 push 在資料陣列末尾加入一個新的標籤 "新項目" 以及對應的數值 75,然後呼叫 update() 使圖表重新繪製,新的數據會以動畫效果長出一個新的長條或扇區(取決於圖表類型)。接著,示範了如何直接修改陣列中的某個值(將第一個數值改為95),修改後再次呼叫 update(),圖表中的第一個元素高度或大小也會隨之改變。最後,我們示範了移除資料:透過 pop() 刪除陣列中的最後一個元素(記得同時從 labels 與對應的 data 陣列各刪除一次),然後再 update() 重新繪圖,圖表的最後一個資料點會隨之消失。

值得注意的是,每當呼叫 chart.update() 時,Chart.js 都會以平滑的動畫過渡方式更新圖表,讓使用者清楚地看到變化過程而不會覺得突然。這使得即時資料視覺化在課堂演示中更加順暢和具吸引力。例如,您可以結合 setInterval 定時更新資料,以模擬即時數據串流,Chart.js 將自動為變化的部分套用動畫效果,讓學生能直觀感受到數據的變動。

常見問題解答

問:圖表已按範例寫好程式碼,為何在瀏覽器中沒有顯示?

答: 如果圖表沒有出現,可能的原因有幾種。首先,請確認已正確引入 Chart.js 的腳本(例如使用 CDN 連結),且 <canvas> 元素的 ID 與 JavaScript 程式碼中使用的 ID 完全一致。如果腳本執行時瀏覽器主控台出現錯誤,請檢查程式碼中的逗號、花括號是否匹配正確。另一個常見問題是腳本執行時機:若您將初始化圖表的 <script> 放在頁面 <head> 中,務必在標籤上加上 defer 屬性或將程式碼放到 <body> 底部,確保在 DOM 元素載入完成後再執行,否則 document.getElementById() 可能找不到對應的 canvas 元素而導致圖表無法繪製。

問:如何調整圖表的大小?圖表可以自適應螢幕大小嗎?

答: Chart.js 圖表的大小通常由 <canvas> 元素的寬高決定。如果您未手動設定寬高,Chart.js 會讓圖表自動填滿容器的寬度。Chart.js 預設是響應式的,圖表會隨瀏覽器視窗大小變化自動縮放。如果想設定固定大小,可以在 HTML 中指定 <canvas> 的 width 和 height 屬性,例如 <canvas id="myChart" width="600" height="400"></canvas>。在響應式模式下,您也可以透過 options.aspectRatio 或 options.maintainAspectRatio 等參數來調整寬高比;例如將 maintainAspectRatio: false 設定後,圖表可以不維持原始長寬比例而自由拉伸以填滿容器。

問:可以在同一張圖上展示多組資料嗎?

答: 可以的。一個 Chart.js 圖表的 datasets 陣列可以包含多個資料集。例如,在折線圖中加入兩組資料,分別給每組資料設置不同的 label 和數值陣列,Chart.js 就會繪製出兩條折線並用不同顏色區分,圖例中也會出現兩個項目讓使用者切換顯示。同樣地,長條圖也可以透過多個資料集來實現「群組式」長條的效果(例如比較不同年份或不同類別的長條)。您只需在 data.datasets 中加入多個物件,每個物件代表一組資料並設定自己的 label、data 和樣式,Chart.js 會自動將它們繪製在同一個圖表上。

問:如何在圓餅圖(或其他圖表)上顯示百分比而不是原始值?

答: 預設情況下,Chart.js 的 tooltip 會顯示資料的原始數值。如果您想顯示百分比,需要自行計算並格式化顯示。最簡單的方法是利用 Chart.js 的選項來定制 tooltip 的回呼函式。例如:

JavaScript
options: {
  plugins: {
    tooltip: {
      callbacks: {
        label: function(context) {
          let dataset = context.dataset;
          let currentValue = dataset.data[context.dataIndex];
          // 計算百分比
          let total = dataset.data.reduce((a, b) => a + b, 0);
          let percentage = ((currentValue / total) * 100).toFixed(1);
          return `${context.label}: ${percentage}%`;
        }
      }
    }
  }
}

上述 tooltip.callbacks.label 函式會攔截預設的提示文字,改為顯示每個扇區對應的百分比(保留一位小數)。除此之外,您也可以使用 Chart.js 的插件(如 chartjs-plugin-datalabels)直接在圖表區域內部顯示百分比標籤。依需求不同有多種方式可以達成百分比顯示,關鍵是在於使用 Chart.js 提供的 API 來格式化輸出內容。

問:我在網路上找到的 Chart.js 範例代碼有些與此不同,應該以哪個為準?

答: Chart.js 在過去的版本中曾經對配置語法做過改動。如果您看到的範例使用的屬性名稱和本教學不同,例如使用 options.legend 而非 options.plugins.legend,或者 yAxes 陣列而非 scales.y,這可能是舊版 Chart.js(如 2.x)的語法。建議您優先參考 Chart.js 官方文件或近期的教學資源,並使用最新版本的 Chart.js。以本篇文章的示範(基於 Chart.js 3.x/4.x)為準,可以確保您使用的是較新的語法和功能。如果您繼承了舊有專案,則需要對照升級指南將設定調整到新版本的格式。

問:Chart.js 是免費的嗎?可以安心用於教學或商業專案嗎?

答: 是的,Chart.js 是一個開源的前端庫,使用 MIT 授權。這意味著您可以自由地在個人、教育甚至商業專案中使用它,而不必擔心授權費用或限制。對教育者而言,這點尤其友好:您可以放心地將 Chart.js 引入課程範例或學術專案中,同時也鼓勵學生在自己的作品中運用。只要遵守 MIT 授權中簡單的版權宣告保留條款(通常只需在您的程式碼中保留 Chart.js 原始碼的版權註記),就可以合法地使用和修改 Chart.js。

結語

透過本篇教學,我們從零開始實作了多種互動圖表,包括折線圖、長條圖與圓餅圖,並深入探索了 Chart.js 的基本設定和互動功能。在教育場域中,善用這些圖表可以將原本抽象的數據轉化為具體的視覺經驗,幫助學生更直觀地理解所學內容。您現在應該熟悉如何在純 HTML/JavaScript 環境下引入 Chart.js、配置各種圖表類型,以及利用事件監聽與資料更新來增強圖表的互動性。

當然,Chart.js 能做的不僅於此。我們僅僅展示了其中三種基本的圖表類型,而 Chart.js 還支援雷達圖、氣泡圖、極區圖等更多元的圖表形式,允許您為不同的資料特性選擇最佳的視覺化方式。此外,您可以深入研究 Chart.js 的插件體系(例如前面提及的資料標籤插件),或學習如何客製更多圖表樣式(如刻度樣式、動畫效果等),以打造更豐富的互動體驗。如果未來您或您的學生對資料視覺化有更高階的需求,Chart.js 的官方文件和活躍社群也提供了大量範例與討論,值得持續學習與挖掘。

希望透過本篇範例講解,您已經掌握 Chart.js 的基礎用法,並對在教學中應用互動圖表充滿信心。透過不斷練習與創作,您將能設計出貼合課程內容的精彩圖表,讓數據教學不再枯燥乏味,而是充滿動態與視覺的魅力。祝您在教學與開發的旅程中玩轉圖表,開拓出更多創新的教學呈現方式!

CONTACT US

網站設計報價洽詢

請填寫您的資料,我們將儘快與您聯繫! 為必填