wishing you all a happy week
I was wondering if you could help me, I'm using Chartjs from the server side to apply charts in reports and call them from the frontend.
The technologies that I am using is nodejs node developed with typescript and express and I am using handlebars for HTML templates, integrate Chartjs, since in addition to being free it is highly recommended in the community, but right now I am having some problems with the implementation
To better integrate the charts from the server I am using chartjs-node-canvas
and generating images through the library,once I have the image I pass it to my template
So what I want to add sub tags to group the information, adding multilevel category tags, but it throws me the following error when I want to use the hooks in the plugins
image1 of the error
How to properly access Chartjs plugin hooks?
In the end, I would like to achieve something like this:
example of the expected result
I leave the code of the configuration of my graph, any type of help would be very grateful, I am new to the community, I hope I have written the question correctly. Thank you very much to all
import {
ChartJSNodeCanvas
} from "chartjs-node-canvas";
const canvasRenderService = new ChartJSNodeCanvas({
width: 1100,
height: 700,
chartCallback: (ChartJS) => {
ChartJS.register(require('chartjs-plugin-datalabels'))
}
});
const mkChart = await canvasRenderService.renderToBuffer({
type: 'bar',
data: {
labels: labels,
datasets: [{
type: 'line',
label: '% ACTIVITY',
backgroundColor: '#FF7605',
borderColor: '#FF7605',
data: lineBar,
datalabels: {
anchor: 'start',
align: 'center',
clamp: true,
backgroundColor: '#FF7605',
color: 'white',
font: {
weight: 'bold'
}
}
},
{
type: 'bar',
label: 'WEEKLY SUMMARY OF HOURS',
backgroundColor: '#222A35',
borderColor: '#222A35',
data: barHorizontal,
datalabels: {
rotation: 270,
padding: 10
}
},
{
type: 'bar',
label: 'HOURS',
backgroundColor: '#008582',
borderColor: '#008582',
data: colbWeekly,
datalabels: {
anchor: 'end',
align: 'top',
clamp: true,
backgroundColor: '#008582',
color: 'white',
font: {
weight: 'bold'
}
}
}
]
},
options: {
plugins: {
datalabels: {
color: 'white',
font: {
weight: 'bold'
},
},
title: {
display: true,
text: 'AVERAGE WEEKLY HOURS'
},
afterDatasetsDraw(chart, args, pluginOptions) {
const {
ctx,
chartArea: {
left,
right,
top,
bottom,
width,
height
}
} = chart;
ctx.save();
ctx.font = 'bolder 12px sans-serif';
ctx.fillStyle = 'rgba(102, 102, 102, 1)';
ctx.textAlign = 'center';
ctx.fillText('WEEK 1', width / 4 + left, bottom + 30)
}
},
elements: {
line: {
fill: false
}
},
scales: {
xAxis: {
stacked: true,
ticks: {
minRotation: 90
},
grid: {
display: false
}
}
}
}
});
You can't access the plugin hooks from a specific plugin within the config of that plugin, you will need to create your own custom plugin and in the plugin itself you can access all the hooks:
const customPlugin = {
id: 'customPlugin',
afterDatasetsDraw: (chart, args, opts) => {
console.log('afterDatasetsDraw')
},
beforeDatasetsDraw: (chart, args, opts) => {
console.log('beforeDatasetsDraw');
}
// You can add all the other hooks here
}
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {},
plugins: [customPlugin]
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.js"></script>
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
</body>
Related
I want to add datalabels to the top of each bar and color them in black and make it in bigger font. Like this:
my chart with necessary labels
But all that I tried don't change the chart.
I add chartjs and charts-plugin-datalabels:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.js"></script>
Chart creating function:
function bars_chart(data, period) {
Chart.register(ChartDataLabels)
document.querySelector('#chartContainer').innerHTML = '<canvas id="bar-chart-horizontal"></canvas>'
var chartConfig = {
type: 'bar',
data: {
labels: period,
datasets: data
},
options: {
responsive: true,
plugins: {
dataLabels: {
font: {
color: "#000000",
size: 25
},
color: "#000000"
},
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Bar Chart'
},
}
},
};
new Chart(document.getElementById("bar-chart-horizontal"), chartConfig);
}
It looks like there is a simple solution but I can't find it)
Your namespace is wrong, you putted a capital L in there while it needs to be fully lower case. After that you can set anchor and align to 'end' to get the value on top of the bars:
Chart.register(ChartDataLabels)
const options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'pink'
}]
},
options: {
plugins: {
datalabels: {
color: 'black',
font: {
size: 40
},
anchor: 'end',
align: 'end'
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.js"></script>
</body>
I am working on project that requires me to design a chart as the following diagram:
I am using chart.js and react to make the distribution plot. But I am not able to figure out how to add fill color of the area chart between a particular range of values of the x-variable. So far, I am able to achieve this:
I have used the following code to make the area chart as a react component:
const data = {
labels: {DataLabel},
datasets: [
{
label: 'Blood Sugar Measure',
data: {Data},
fill: true,
backgroundColor: ["#E5E5E5", "#E5E5E5", "#B4EDB3", "#B4EDB3", "#E5E5E5"],
pointBorderColor: "#8884d8",
pointBorderWidth: 2,
pointRadius: 3,
tension: 0.4
},
],
};
const options = {
plugins: { legend: { display: false } },
layout: { padding: { bottom: 0.1 } },
scales: {
y: {
display : false,
beginAtZero: true,
grid: {
display: false
},
ticks: {
color: "#000000",
font: {
size: 18
}
}
},
x: {
beginAtZero: true,
grid: {
display: false
},
ticks: {
color: "#000000",
font: {
size: 10
},
min: 0
}
}
},
};
export const DistChart = () => {
return (<div className="App">
<Line data={data} options={options} />
</div>);
};
I would need some help to apply the conditional fill color based on the x-axis variable.
You can use multiple datasets with object data so you can specify starting and end points. After this you can manipulate the legend so it looks like its only a single dataset:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: 'Blood Sugar Measure extra',
data: [{
x: "Red",
y: 5
}, {
x: "Blue",
y: 8
}],
backgroundColor: 'lightGray',
fill: true
},
{
label: 'Blood Sugar Measure',
data: [{
x: "Blue",
y: 8
}, {
x: "Yellow",
y: 12
}, {
x: "Green",
y: 10
}],
backgroundColor: 'pink',
fill: true
},
{
label: 'Blood Sugar Measure extra',
data: [{
x: "Green",
y: 10
}, {
x: "Purple",
y: 12
}, {
x: "Orange",
y: 10
}],
backgroundColor: 'lightGray',
fill: true
}
]
},
options: {
plugins: {
legend: {
onClick: (e, legendItem, legend) => {
const ci = legend.chart;
const currentlyHidden = ci.getDatasetMeta(0).hidden;
for (let i = 0; i < ci.data.datasets.length; i++) {
ci.setDatasetVisibility(i, currentlyHidden)
}
ci.update();
},
labels: {
filter: (e) => (!e.text.includes('extra'))
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
I was able to make some progress on the design that I wanted, so thought of sharing my answer to benefit others. I was able to fill based on x-axis data values and get the following chart:
I had to use the segment property inside data configs to achieve this, with the help of a function. This is the modified code:
const highlightRegion = (ctx, value) => {
if (ctx.p0DataIndex > boundary_val1 && ctx.p0DataIndex < boundary_val2) {
return "#B4EDB3";
}
return "#E5E5E5";
};
const bgColor = ctx => highlightRegion(ctx, "#B4EDB3");
const data = {
labels: x_values,
datasets: [
{
label: 'Count',
data: [0, 20, 40, 80, 150, 80, 30, 0],
pointRadius: 0,
fill: true,
tension: 0.4,
segment: {
backgroundColor: bgColor,
borderColor: bgColor,
},
},
],
};
Special thanks goes to this youtube series from where I was able to find my answer: https://www.youtube.com/watch?v=st2O-pvhWM4.
I will keep this post open, in case if there is a better solution as I think my solution is not absolutely correct.
I'm using line chart js to display a graph and I'm trying to calculate the difference between the selected point and the previous one and render it in a tool tip.
I've read that I should use callbacks function but when I tried it nothing happen.
Even I only try to change the tittle
Here's my options for my line chart if anyone can help :)
Chart js version : 3.6.1
plugins: {
legend: {
display: false
},
title: {
display: true,
font: {
size: 18,
},
color: "white"
},
zoom: {
zoom: {
drag: {
enabled: true
},
mode: 'xy',
}
},
tooltip: {
callbacks: {
title: function () {
return "my tittle";
}
}
}
}
This is because you are using V2 syntax in with V3, you can read the namespace in the options.
Tooltip has been moved to the plugins section
For all changes please read the migration guide
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'orange'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'pink'
}
]
},
options: {
plugins: {
tooltip: {
callbacks: {
title: () => ('Title')
}
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.2/chart.js"></script>
</body>
So I have 2 datasets, and I would like to have one y-axis to be bigger and one smaller if you know what I mean.
The Return Procent datas are somewhere between 20-100, but price can be small like 0.06 or something. And it makes the chart useless. How can I make two different size y-axis?
var ctx = document.getElementById('skinsChart').getContext('2d');
var skinsChart = new Chart(ctx, {
type: 'line',
data: {
labels: [ < ? php echo $date; ? > ],
datasets: [{
label: 'Return Procent',
data: ["65.7", "63.7", "69.7", "62.7"],
borderColor: 'rgb(0,0,0)',
borderWidth: 1,
backgroundColor: 'rgba(0,0,0,0.2)'
}, {
label: 'Price',
data: ["0.07", "0.08", "0.06", "0.07"],
borderColor: 'rgb(255,0,0)',
borderWidth: 1,
backgroundColor: 'rgba(0,0,0,0.2)'
}]
},
options: {
scales: {
yAxes: [{
beginAtZero: false
}]
},
elements: {
point: {
radius: 0
}
}
}
});
You need to define multiple y-axes as explained in chapter Create Multiple Axis from the Chart.js documentation.
Please take a look at your amended code and see how it works.
var ctx = document.getElementById('skinsChart').getContext('2d');
var skinsChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['A', 'B', 'C', 'D'],
datasets: [{
label: 'Return Procent',
data: ["65.7", "63.7", "69.7", "62.7"],
borderColor: 'rgb(0,0,0)',
borderWidth: 1,
backgroundColor: 'rgba(0,0,0,0.2)',
yAxisID: 'yLeft'
}, {
label: 'Price',
data: ["0.07", "0.08", "0.06", "0.07"],
borderColor: 'rgb(255,0,0)',
borderWidth: 1,
backgroundColor: 'rgba(0,0,0,0.2)',
yAxisID: 'yRight'
}]
},
options: {
scales: {
yAxes: [{
id: 'yLeft',
},
{
id: 'yRight',
position: 'right',
}]
},
elements: {
point: {
radius: 0
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="skinsChart" height="100"></canvas>
Here is my chart:
And here is the chart I need:
The difference is that first chart doesn't have borders but second has 2 of them: white and gray
These are the options I use:
let activityTypeChart = new Chart(document.getElementById("pie-chart-activity-type-widget"), {
type: 'doughnut',
data: {
labels,
datasets: [{
label: "Average Duration of Each Task Type",
backgroundColor: colors,
data: GetActivityTypeCounters(),
}],
},
options: {
title: {
display: false,
},
legend: {
display: false,
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.labels[tooltipItem.index] || '';
return label;
}
}
},
cutoutPercentage: 65,
hover: {
onHover: function(e, a) {
$("#activity-type-widget").css("cursor", a[0] ? "pointer" : "default");
}
}
},
});
If I try to use border, borderWidth, etc., the border actually has only 1 color. Is there a way to set 2 or more borders, maybe using gradient somehow?
Since you didn't receive an answer so far, I allow myself to propose a solution that works in case your chart is of a fixed size. This is far from being a perfect solution but the user won't notice the rather weird code behind.
You can fake the outer and inner borders by defining additional datasets as shown in the code snippet below.
new Chart("myChart", {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow"],
datasets: [{
data: [1, 1, 1],
borderColor: "#CCCCCC",
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"], // required for correct legend colors
weight: 0.01,
borderWidth: 1
},
{
data: [1],
backgroundColor: "#FFFFFF",
hoverBackgroundColor: "#FFFFFF",
weight: 0.1,
borderWidth: 1
},
{
data: [200, 100, 25],
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"],
},
{
data: [1],
backgroundColor: "#FFFFFF",
hoverBackgroundColor: "#FFFFFF",
weight: 0.1,
borderWidth: 0
},
{
data: [1, 1, 1],
borderColor: "#CCCCCC",
weight: 0.03,
borderWidth: 1
}]
},
options: {
legend: {
display: true
},
tooltips: {
filter: tooltipItem => tooltipItem.datasetIndex == 2
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="myChart" height="80"></canvas>