經手的幾個專案,echarts 套件改成 Chart.js 的工作在終於告一段落,今天解決的最後一個問題是,在 X 軸的每個區間有三個長條圖,同時在長條圖上要要一個點來跑線圖,結果如下圖。簡單筆記一下作法,順便複習一下今天做的過程。
比較難用語言描述要畫的圖,直接看最後結果吧。

因為 Chart.js 原始設定, 折線圖在每一個 X 軸區間只能畫一個點,而且是畫在每個區間的正中央,如果要在每一隻長條圖上畫點,需要另外寫 plugin。
設置 <canvas>
<div class="chartCard">
<div class="chartBox">
<canvas id="myChart"></canvas>
</div>
</div>資料設定
const data = {
labels: ["2022-10-20", "2022-10-21"],
datasets: [
{
label: "Red Sales",
type: "bar",
order: 1,
data: [18, 12, 6, 9, 12, 3, 9],
backgroundColor: ["rgba(255, 26, 104, 0.2)"],
borderColor: ["rgba(255, 26, 104, 1)"],
borderWidth: 1,
},
{
label: "Blue Sales",
type: "bar",
order: 1,
data: [12, 9, 6, 9, 12, 3, 9],
backgroundColor: ["rgba(54, 162, 235, 0.2)"],
borderColor: ["rgba(54, 162, 235, 1)"],
borderWidth: 1,
},
{
label: "Yellow Sales",
type: "bar",
order: 1,
data: [6, 6, 6, 9, 12, 3, 9],
backgroundColor: ["rgba(255, 206, 86, 0.2)"],
borderColor: ["rgba(255, 206, 86, 1)"],
borderWidth: 1,
},
{
label: "Black Sales",
type: "line",
order: 0,
data: [
{ x: "2022-10-20", y: 1 },
{ x: "2022-10-20", y: 2 },
{ x: "2022-10-20", y: 3 },
{ x: "2022-10-21", y: 6 },
{ x: "2022-10-21", y: 9 },
{ x: "2022-10-21", y: 12 },
],
backgroundColor: ["rgba(0, 0, 0, 0.2)"],
borderColor: ["rgba(0, 0, 0, 1)"],
borderWidth: 1,
},
],
};要注意:Black Sales 的 data 格式,和 Red Sales、Blue Sales 及 Yellow Sales 都不同。陣列裡面放的是物件,裡面 x 對應的是每一隻長條圖的 X 軸,y 則是折線圖每個數值的高度。
{
label: "Black Sales",
type: "line",
order: 0,
data: [
{ x: "2022-10-20", y: 1 },
{ x: "2022-10-20", y: 2 },
{ x: "2022-10-20", y: 3 },
{ x: "2022-10-21", y: 6 },
{ x: "2022-10-21", y: 9 },
{ x: "2022-10-21", y: 12 },
],
backgroundColor: ["rgba(0, 0, 0, 0.2)"],
borderColor: ["rgba(0, 0, 0, 1)"],
borderWidth: 1,
},設定 lineAlignment 物件
lineAlignment 要放到 plugin 中,會在長條圖畫完之後,接著劃出點圖。
const lineAlignment = {
id: "lineAlignment",
afterDatasetsDraw(chart, args, pluginOptions) {
// console.log(chart.getDatasetMeta(0));
const {
scales: { x },
data,
} = chart;
const lastDataset = data.datasets.length - 1;
const xCoor = [];
for (let i = 0; i < data.labels.length; i++) {
// console.log(chart.getDatasetMeta(0).data[1].x)
xCoor.push(chart.getDatasetMeta(0).data[i].x);
xCoor.push(chart.getDatasetMeta(1).data[i].x);
xCoor.push(chart.getDatasetMeta(2).data[i].x);
}
chart.getDatasetMeta(lastDataset).data.forEach((dataPoint,index) => {
dataPoint.x = xCoor[index]
dataPoint.options.borderWidth = 0;
});
console.log(chart.getDatasetMeta(lastDataset));
},
};設定config
const config = {
data,
options: {
scales: {
x: {
// type: "time",
// time: {
// unit: "day",
// },
},
y: {
beginAtZero: true,
},
},
},
plugins: [lineAlignment],
};
畫圖
const myChart = new Chart(document.getElementById("myChart"), config);