365 lines
10 KiB
JavaScript
365 lines
10 KiB
JavaScript
Chart.register(ChartDataLabels);
|
|
const charts = {};
|
|
|
|
|
|
function buildStackedChart(canvasId, labels, datasets) {
|
|
const ctx = document.getElementById(canvasId);
|
|
|
|
if (!ctx) return;
|
|
|
|
if (charts[canvasId]) {
|
|
charts[canvasId].destroy();
|
|
}
|
|
|
|
charts[canvasId] = new Chart(ctx, {
|
|
|
|
type: "bar",
|
|
|
|
data: {
|
|
labels: labels,
|
|
datasets: datasets,
|
|
datalabels: {
|
|
display: true
|
|
}
|
|
},
|
|
|
|
plugins: [ChartDataLabels],
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
|
|
layout: {
|
|
padding: {
|
|
top: 20,
|
|
bottom: 30
|
|
}
|
|
},
|
|
|
|
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom',
|
|
align: 'center',
|
|
|
|
labels: {
|
|
padding: 20,
|
|
boxWidth: 10,
|
|
boxHeight: 10,
|
|
usePointStyle: true,
|
|
pointStyle: 'circle'
|
|
}
|
|
},
|
|
datalabels: {
|
|
color: "#000",
|
|
anchor: "end",
|
|
align: "top",
|
|
clamp: true,
|
|
clip: false,
|
|
font: {
|
|
weight: "bold",
|
|
size: 10
|
|
},
|
|
formatter: function (value) {
|
|
return value > 0 ? value : null;
|
|
}
|
|
}
|
|
},
|
|
|
|
scales: {
|
|
x: {
|
|
stacked: true
|
|
},
|
|
y: {
|
|
stacked: true,
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
function buildChart(id, type, labels, data) {
|
|
|
|
const ctx = document.getElementById(id);
|
|
|
|
if (!ctx) return;
|
|
|
|
if (charts[id]) charts[id].destroy();
|
|
|
|
charts[id] = new Chart(ctx, {
|
|
type: type,
|
|
data: {
|
|
labels: labels,
|
|
datasets: [{
|
|
data: data,
|
|
borderWidth: 2,
|
|
tension: 0.3,
|
|
barPercentage: 0.8,
|
|
categoryPercentage: 0.6,
|
|
maxBarThickness: 50
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
|
|
layout: {
|
|
padding: {
|
|
top: 30,
|
|
bottom: 30
|
|
}
|
|
},
|
|
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom',
|
|
align: 'center',
|
|
display: type === 'pie' || type === 'doughnut',
|
|
labels: {
|
|
padding: 10,
|
|
boxWidth: 14,
|
|
boxHeight: 14,
|
|
usePointStyle: true,
|
|
pointStyle: 'circle'
|
|
}
|
|
},
|
|
datalabels: {
|
|
color: "#282626",
|
|
anchor: type === "bar" ? "end" : "center",
|
|
align: type === "bar" ? "top" : "center",
|
|
font: {
|
|
size: 10
|
|
},
|
|
formatter: function(value, ctx) {
|
|
const data = ctx.chart.data.datasets[0].data;
|
|
const total = data.reduce((a, b) => a + b, 0);
|
|
const percent = total ? (value / total * 100).toFixed(1) : 0;
|
|
return percent + '%';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
|
|
|
|
const ctx = document.getElementById(canvasId);
|
|
if (!ctx) return;
|
|
|
|
if (charts[canvasId]) charts[canvasId].destroy();
|
|
|
|
charts[canvasId] = new Chart(ctx, {
|
|
|
|
data: {
|
|
labels: labels,
|
|
datasets: [
|
|
|
|
{
|
|
type: 'line',
|
|
label: 'Influenza %',
|
|
data: fluRate,
|
|
borderColor: '#fa2929',
|
|
backgroundColor: '#fa2929',
|
|
tension: 0.4,
|
|
yAxisID: 'y1',
|
|
pointStyle: 'line',
|
|
|
|
},
|
|
|
|
|
|
{
|
|
type: 'line',
|
|
label: 'COVID-19 %',
|
|
data: covidRate,
|
|
borderColor: '#1976D2',
|
|
backgroundColor: '#1976D2',
|
|
tension: 0.4,
|
|
yAxisID: 'y1',
|
|
pointStyle: 'line',
|
|
},
|
|
|
|
|
|
{
|
|
type: 'bar',
|
|
label: 'Total Cases',
|
|
data: samples,
|
|
backgroundColor: '#0B8F3C',
|
|
borderRadius: 2,
|
|
barPercentage: 0.8,
|
|
categoryPercentage: 0.7,
|
|
yAxisID: 'y',
|
|
}
|
|
|
|
]
|
|
},
|
|
|
|
plugins: [ChartDataLabels],
|
|
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom',
|
|
labels: {
|
|
usePointStyle: true,
|
|
padding: 20
|
|
}
|
|
},
|
|
datalabels: {
|
|
align: "top",
|
|
anchor: "end",
|
|
color: "#555",
|
|
font: {
|
|
size: 10
|
|
},
|
|
formatter: function (value, context) {
|
|
if (Number(value) === 0) return null;
|
|
|
|
if (context.dataset.type === 'line') {
|
|
return value + '%';
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|
|
},
|
|
layout: {
|
|
padding: {
|
|
top: 30,
|
|
bottom: 20
|
|
}
|
|
},
|
|
|
|
scales: {
|
|
y: {
|
|
position: 'left',
|
|
title: {
|
|
display: true,
|
|
text: 'Cases'
|
|
}
|
|
},
|
|
y1: {
|
|
position: 'right',
|
|
grid: { drawOnChartArea: false },
|
|
title: {
|
|
display: true,
|
|
text: '% Positivity'
|
|
},
|
|
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
// function buildMixedTrendChart(canvasId, labels, samples, positivity) {
|
|
|
|
// const ctx = document.getElementById(canvasId);
|
|
// if (!ctx) return;
|
|
|
|
// if (charts[canvasId]) charts[canvasId].destroy();
|
|
|
|
// charts[canvasId] = new Chart(ctx, {
|
|
// data: {
|
|
// labels: labels,
|
|
// datasets: [
|
|
// {
|
|
// type: 'line',
|
|
// label: '% Positive',
|
|
// data: positivity,
|
|
// borderColor: '#1e6ef2',
|
|
// borderWidth: 2,
|
|
// tension: 0.4,
|
|
// fill: false,
|
|
// pointRadius: 2,
|
|
// pointStyle: 'line',
|
|
// yAxisID: 'y1',
|
|
|
|
|
|
// },
|
|
|
|
// {
|
|
// type: 'bar',
|
|
// label: 'Total sample ',
|
|
// data: samples,
|
|
// backgroundColor: '#2ecc71',
|
|
// borderRadius: 2,
|
|
// barPercentage: 0.8,
|
|
// categoryPercentage: 0.7,
|
|
// yAxisID: 'y',
|
|
|
|
// }
|
|
// ]
|
|
// },
|
|
|
|
// plugins: [ChartDataLabels],
|
|
|
|
// options: {
|
|
// responsive: true,
|
|
// maintainAspectRatio: false,
|
|
|
|
// plugins: {
|
|
// legend: {
|
|
// position: 'bottom',
|
|
// align: 'center',
|
|
// labels: {
|
|
// usePointStyle: true,
|
|
// padding: 20,
|
|
// boxWidth: 30,
|
|
// font: { size: 12 }
|
|
// }
|
|
// },
|
|
// datalabels: {
|
|
// align: "top",
|
|
// anchor: "end",
|
|
// color: "#555",
|
|
// font: {
|
|
// size: 10
|
|
// },
|
|
// formatter: function (value, context) {
|
|
|
|
// if (Number(value) === 0) return null;
|
|
// if (context.dataset.type === 'line') {
|
|
// console.log(value);
|
|
// return value + '%';
|
|
// }
|
|
|
|
// return value;
|
|
// }
|
|
// }
|
|
// },
|
|
|
|
// layout: {
|
|
// padding: {
|
|
// top: 20,
|
|
// bottom: 50
|
|
// }
|
|
// },
|
|
|
|
// scales: {
|
|
// y: {
|
|
// position: 'left',
|
|
// title: {
|
|
// display: true,
|
|
// text: 'Total sample'
|
|
// }
|
|
// },
|
|
|
|
// y1: {
|
|
// position: 'right',
|
|
// grid: {
|
|
// drawOnChartArea: false
|
|
// },
|
|
// title: {
|
|
// display: true,
|
|
// text: '% Positive'
|
|
// },
|
|
// ticks: {
|
|
// callback: value => value + '%'
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// });
|
|
// }
|