Chart.js 組件註冊
概述
從 Chart.js v3.0 開始,為了支援 tree-shaking 和減少 bundle size,Chart.js 採用了模組化設計。所有的圖表組件(scales、elements、plugins)都需要手動註冊才能使用。本文件說明如何在 Angular 專案中正確註冊 Chart.js 組件。
版本演進對比
ng2-charts v5.x + Chart.js v4.x(舊版本)
// NgChartsModule 內部自動註冊常用組件
import { NgChartsModule } from 'ng2-charts';
@Component({
imports: [NgChartsModule], // 自動處理註冊
})
export class ChartComponent {}
特點:
✅ NgChartsModule 自動註冊常用組件
✅ 開箱即用,無需手動設定
🔶 仍使用 Chart.js v4.x 的模組化架構
🔶 Bundle 包含 NgChartsModule 預設註冊的組件
ng2-charts v6.x+ + Chart.js v4.x(新版本)
// 移除 NgChartsModule,完全交由開發者控制
import { BaseChartDirective } from 'ng2-charts';
import { Chart, CategoryScale, LinearScale, BarElement } from 'chart.js';
// 必須手動註冊組件
Chart.register(CategoryScale, LinearScale, BarElement);
@Component({
imports: [BaseChartDirective], // 只提供 directive
})
export class ChartComponent {}
特點:
✅ 完全控制需要的組件,最佳化 bundle size
✅ 更好的 tree-shaking 支援
✅ 避免不必要的組件載入
❌ 需要手動註冊所有組件
ng2-charts 版本對應
v4.x
v3.x
✅ 支援
✅ 完全
❌ 不需要
15-16
v5.x
v4.x
✅ 支援
✅ 部分
❌ 不需要
16-17
v6.x
v4.x
❌ 移除
❌ 無
✅ 必須
17+
v8.x
v4.x
❌ 移除
❌ 無
✅ 必須
19+
重要轉折點:ng2-charts v5 → v6
ng2-charts v5.x 的 NgChartsModule 做了什麼?
// NgChartsModule 內部大概是這樣:
@NgModule({
// 在模組載入時自動註冊常用組件
imports: [],
providers: []
})
export class NgChartsModule {
constructor() {
// 自動註冊基本組件
Chart.register(
CategoryScale,
LinearScale,
BarElement,
LineElement,
PointElement,
Title,
Tooltip,
Legend
// ... 其他常用組件
);
}
}
ng2-charts v6.x 的變化
完全移除
NgChartsModule
只提供
BaseChartDirective
所有註冊責任轉移給開發者
註冊方式
方式一:全域註冊(推薦)
在 main.ts
中註冊所有需要的組件:
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
// 導入 Chart.js 組件
import { Chart, registerables } from 'chart.js';
// 註冊所有預設組件(最簡單的方式)
Chart.register(...registerables);
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
方式二:按需註冊(效能最佳)
只註冊專案中實際使用的組件:
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
// 按需導入組件
import {
Chart,
CategoryScale, // X 軸類別刻度
LinearScale, // Y 軸線性刻度
BarElement, // 長條圖元素
LineElement, // 折線圖元素
PointElement, // 點元素
ArcElement, // 圓弧元素(餅圖、甜甜圈圖)
Title, // 標題插件
Tooltip, // 提示框插件
Legend, // 圖例插件
Filler, // 填充插件
Colors // 顏色插件
} from 'chart.js';
// 只註冊需要的組件
Chart.register(
CategoryScale,
LinearScale,
BarElement,
LineElement,
PointElement,
ArcElement,
Title,
Tooltip,
Legend,
Filler,
Colors
);
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
方式三:組件級註冊
在特定組件中註冊(不推薦用於共用組件):
// chart.component.ts
import { Component, OnInit } from '@angular/core';
import { Chart, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js';
@Component({
selector: 'app-chart',
// ...
})
export class ChartComponent implements OnInit {
ngOnInit() {
// 在組件初始化時註冊
Chart.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
}
}
常用組件清單
Scales(刻度)
import {
CategoryScale, // 類別刻度(X 軸常用)
LinearScale, // 線性刻度(Y 軸常用)
LogarithmicScale, // 對數刻度
RadialLinearScale, // 徑向線性刻度(雷達圖)
TimeScale, // 時間刻度
TimeSeriesScale, // 時間序列刻度
} from 'chart.js';
Elements(圖表元素)
import {
BarElement, // 長條圖
LineElement, // 折線圖
PointElement, // 點(折線圖的點)
ArcElement, // 圓弧(餅圖、甜甜圈圖)
} from 'chart.js';
Plugins(插件)
import {
Title, // 標題
Tooltip, // 提示框
Legend, // 圖例
Filler, // 區域填充
Colors, // 自動顏色
Decimation, // 資料抽樣
SubTitle, // 副標題
} from 'chart.js';
Controllers(圖表控制器)
import {
BarController, // 長條圖控制器
LineController, // 折線圖控制器
PieController, // 餅圖控制器
DoughnutController,// 甜甜圈圖控制器
RadarController, // 雷達圖控制器
ScatterController, // 散佈圖控制器
BubbleController, // 泡泡圖控制器
PolarAreaController,// 極座標區域圖控制器
} from 'chart.js';
圖表類型對應的必要組件
長條圖(Bar Chart)
Chart.register(
CategoryScale, // X 軸
LinearScale, // Y 軸
BarElement, // 長條元素
Title, // 標題
Tooltip, // 提示框
Legend // 圖例
);
折線圖(Line Chart)
Chart.register(
CategoryScale, // X 軸
LinearScale, // Y 軸
LineElement, // 線元素
PointElement, // 點元素
Filler, // 填充(如果需要區域圖)
Title,
Tooltip,
Legend
);
餅圖(Pie Chart)
Chart.register(
ArcElement, // 圓弧元素
Title,
Tooltip,
Legend
);
雷達圖(Radar Chart)
Chart.register(
RadialLinearScale, // 徑向刻度
LineElement, // 線元素
PointElement, // 點元素
Filler, // 填充
Title,
Tooltip,
Legend
);
常見錯誤排除
錯誤:"category" is not a registered scale
"category" is not a registered scale
ERROR Error: "category" is not a registered scale.
解決方案:註冊 CategoryScale
import { CategoryScale } from 'chart.js';
Chart.register(CategoryScale);
錯誤:"linear" is not a registered scale
"linear" is not a registered scale
ERROR Error: "linear" is not a registered scale.
解決方案:註冊 LinearScale
import { LinearScale } from 'chart.js';
Chart.register(LinearScale);
錯誤:"bar" is not a registered controller
"bar" is not a registered controller
ERROR Error: "bar" is not a registered controller.
解決方案:註冊 BarController 和 BarElement
import { BarController, BarElement } from 'chart.js';
Chart.register(BarController, BarElement);
最佳實踐
1. 使用 registerables(開發階段)
// 開發階段:快速原型開發
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
2. 按需註冊(正式環境)
// 正式環境:最佳化 bundle size
import { Chart, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js';
Chart.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
3. 建立註冊模組
// chart-registration.ts
import {
Chart,
CategoryScale,
LinearScale,
BarElement,
LineElement,
PointElement,
ArcElement,
Title,
Tooltip,
Legend,
Filler,
Colors
} from 'chart.js';
export function registerChartComponents() {
Chart.register(
CategoryScale,
LinearScale,
BarElement,
LineElement,
PointElement,
ArcElement,
Title,
Tooltip,
Legend,
Filler,
Colors
);
}
// main.ts
import { registerChartComponents } from './chart-registration';
registerChartComponents();
Bundle Size 比較
全部註冊 vs 按需註冊
全部註冊 (registerables
)
~180KB
較慢
開發階段、多種圖表
按需註冊(基本組件)
~60KB
較快
正式環境、特定圖表
按需註冊(最小組件)
~40KB
最快
正式環境、單一圖表
升級指引
從 ng2-charts v5.x 升級到 v6.x
1. 更新依賴:
# 檢查目前版本
npm list ng2-charts chart.js
# 更新到新版本
npm install ng2-charts@^6.0.1 chart.js@^4.5.0
2. 修改 import(關鍵變更):
// ❌ 舊版本(v5.x)
import { NgChartsModule } from 'ng2-charts';
@Component({
imports: [NgChartsModule] // NgChartsModule 已被移除
})
// ✅ 新版本(v6.x)
import { BaseChartDirective } from 'ng2-charts';
@Component({
imports: [BaseChartDirective] // 改用 BaseChartDirective
})
3. 新增組件註冊(必要步驟):
// main.ts 中加入
import { Chart, registerables } from 'chart.js';
// 註冊所有組件(推薦用於升級過渡期)
Chart.register(...registerables);
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
4. 驗證升級結果:
# 啟動開發伺服器
ng serve
# 檢查是否出現以下錯誤:
# "category" is not a registered scale
# "linear" is not a registered scale
# "bar" is not a registered controller
升級檢查清單
[ ] 更新 package.json 依賴版本
[ ] 將所有
NgChartsModule
改為BaseChartDirective
[ ] 在 main.ts 中加入
Chart.register(...registerables)
[ ] 移除 imports 中的
NgChartsModule
[ ] 測試所有圖表功能正常
[ ] 檢查 bundle size 是否如預期
常見升級問題
問題 1:Import 錯誤
// 錯誤訊息
Module '"ng2-charts"' has no exported member 'NgChartsModule'
// 解決方案
// 將所有 NgChartsModule 改為 BaseChartDirective
問題 2:Scale 註冊錯誤
// 錯誤訊息
"category" is not a registered scale
// 解決方案
// 在 main.ts 加入組件註冊
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
結論
ng2-charts v5 → v6 的升級帶來了重要的架構變更:
為什麼需要手動註冊?
ng2-charts v5.x 時代:
NgChartsModule
在載入時自動註冊常用的 Chart.js 組件開發者無感,開箱即用
但無法精確控制載入的組件
ng2-charts v6.x 變更:
移除
NgChartsModule
,將控制權完全交給開發者需要手動註冊所有需要的 Chart.js 組件
更好的 tree-shaking 和 bundle size 控制
效能影響分析
v5 + NgChartsModule
~120KB
自動載入預設組件
快速開發
v6 + 全部註冊
~180KB
手動載入所有組件
多種圖表
v6 + 按需註冊
~40-60KB
手動載入需要組件
正式環境
升級建議
升級過渡期:使用
Chart.register(...registerables)
確保功能正常優化階段:分析實際使用的圖表類型,改用按需註冊
維護階段:建立團隊的組件註冊標準和最佳實踐
這個變更雖然增加了設定複雜度,但提供了更好的效能控制能力,特別適合對 bundle size 敏感的正式環境。
Last updated