How to Add filled circle in doghnut chart using chart.js - javascript

I want to add a background color or a cirle with color inside doghnut chart using chartjs.
I have already added text in the center of doghnut chart.
However I am not able to add the background colour.
I also want to remove padding and margin chart.js inserts in the chart
I want a chart like this
I am able to acheive following using below code
This my code to render chart
data = {
labels: [
'performance'
],
datasets: [{
label: 'performance;,
data: [90, 10],
backgroundColor: [
'#27AE60',
'#3333331A'
]
}]
};
config = {
type: 'doughnut',
data,
options: {
cutout: 200,
legend: {
display: false,
},
plugins: {
legend: {
display: false
}
},
responsive: true,
rotation: 210, // start angle in degrees
circumference: 300,
radius: "50%"
},
plugins: [{
id: 'text',
beforeDraw: function (chart, a, b) {
let width = chart.width,
height = chart.height,
ctx = chart.ctx;
ctx.restore();
let fontSize = (height / 200).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
let text = '90%',
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
}],
centerText: {
display: true,
text: "280"
}
};
new Chart('performance', config);

You can mimic this design by using a pie chart with specific configuration options.
Here is a working example, including the posted plugin code for drawing text in the middle (note that the plugin is changed from beforeDraw to afterDraw to keep the text above the fill segment):
const data = {
datasets: [{
label: 'outer',
data: [1, 2],
backgroundColor: [
'#27AE60',
'#3333331A'
],
rotation: 210,
circumference: 300,
cutout: '50%',
borderWidth: 0
}, {
// dummy dataset to fill middle.
label: 'inner',
data: [1],
backgroundColor: '#27AE60',
weight: 3,
borderWidth: 0
}]
};
new Chart('chart', {
type: 'pie',
data: data,
options: {
borderAlign: 'inner'
},
plugins: [{
id: 'text',
afterDraw: function(chart, a, b) {
let width = chart.width,
height = chart.height,
ctx = chart.ctx;
ctx.restore();
let fontSize = (height / 200).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
let text = '90%',
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
}],
});
<div style="width:200px;height:200px"><canvas id="chart"></canvas></div>
<script src="https://cdn.jsdelivr.net/npm/chart.js#4.2.1"></script>

Related

Style Chart.js floating bar chart

I've created a chart in Chart.js that looks like this:
(Full code: https://codepen.io/LondonAppDev/pen/RwMBxPX)
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: 'Range',
data: [
{x: 'A', y: [100, 200]},
{x: 'B', y: [50, 120]}
],
backgroundColor: ['red']
}]
},
options: {
barThickness: 1,
}
});
I'm trying to style the bar so they have markers at the top and bottom like this:
I've looked into CSS but it won't work as the elements are within a canvas.
I'm wondering if there is a style option that would achieve this?
I think there are 2 options:
use Chart error bars plugin: https://github.com/sgratzl/chartjs-chart-error-bars
develop own plugin to do that.
In the below snippet, you can find the options 2 (own plugin)
var plugin = {
id: 'myPlugin',
afterDraw(chart, args) {
const ctx = chart.ctx;
ctx.save();
const meta = chart.getDatasetMeta(0);
for (const data of meta.data) {
const topStart = data.x - 20;
const topEnd = data.x + 20;
ctx.lineWidth = data.options.borderWidth;
ctx.strokeStyle = data.options.backgroundColor;
ctx.beginPath();
ctx.moveTo(topStart, data.y);
ctx.lineTo(topEnd, data.y);
ctx.moveTo(topStart, data.y + data.height);
ctx.lineTo(topEnd, data.y + data.height);
ctx.closePath();
ctx.stroke();
}
ctx.restore();
}
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
plugins: [plugin],
data: {
datasets: [{
label: 'Range',
data: [
{x: 'A', y: [100, 200]},
{x: 'B', y: [50, 120]}
],
backgroundColor: ['red']
}]
},
options: {
barThickness: 1,
}
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/chart.min.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>

Create space between legend and chart in charts.js [duplicate]

This question already has answers here:
Chart.js - Increase spacing between legend and chart
(13 answers)
Closed 1 year ago.
I am working with charts.js but I'm facing an issue. My legend and bar chart value overlaps a bit.
I am not able to resolve this issue, It would be appreciated if there is a solution to this issue
I have shared JS fiddle link below
https://jsfiddle.net/qh0yzmjf/1/
var ctx = document.getElementById("canvas").getContext("2d");
var nomi = [2017, 2018, 2019];
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: nomi,
datasets: [{
label: 'PP PERVENUTI',
data: [50, 30, 45],
backgroundColor: "#8A0808",
fill: false,
borderColor: "#8A0808",
borderWidth: 3
},
{
label: 'PP EVASI',
data: [60, 45, 12],
backgroundColor: "#0B610B",
fill: false,
borderColor: "#0B610B",
borderWidth: 3
},
{
label: 'PI PERVENUTI',
data: [20, 25, 35],
backgroundColor: "#8A0886",
fill: false,
borderColor: "#8A0886",
borderWidth: 3
},
{
label: 'PI EVASI',
data: [10, 20, 30],
backgroundColor: "#0404B4",
fill: false,
borderColor: "#0404B4",
borderWidth: 3
}
]
},
options: {
legend: {
display: true,
position: "top"
},
hover: {
animationDuration: 0
},
animation: {
onComplete: function() {
var ctx = this.chart.ctx;
const chart = this.chart;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.fillStyle = "black";
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function(dataset, i) {
if (chart.getDatasetMeta(i).hidden) {
return;
}
for (var i = 0; i < dataset.data.length; i++) {
for (var key in dataset._meta) {
var model = dataset._meta[key].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y);
}
}
});
}
}
}
});
I have also shared my code above
I don't know how to create space between legend and chart, and help will be appreciated thanks
If I am not wrong, there isnt a configuration built by chart js to put padding between the labels and the chart,although, the padding to the labels are applied in wor format, this means that chart js applies padding between labels, on the other hand, you can apply padding between the title of the chart and the labels.
If you want padding between the tittle of the chart and the chart you can use the following code:
plugins: {
title: {
display: true,
text:'Historico Mensual',
},
legend: {
labels: {
padding: 100
}
}
},
Another solution it could be to change the position of the labels to the bottom with the following code:
options: {
legend: {
display: true,
position: "bottom"
},
And adding a layput padding so the values dont get outside the canvas.
options: {
layout:{
padding:20
}
},

How to apply to different bground color for each area in Chart.js

In react-chartjs-2
In Line chart every grid should have different background colors.
Is this achievable with this library?
This is how LineChart should looks:
This is my Code/configuration:
const options = {
responsive: true,
scales: {
y: {
grid: {
backgroundColor: [
'rgba(36, 206, 0, 0.8)',
'rgba(255, 255, 0, .8)',
'rgba(255, 162, 0, 0.8)',
'rgba(36, 206, 0, 0.8)',
],
},
};
Thanks for reading.
You can use an inline plugin to achieve it:
var GradientBgPlugin = {
beforeDraw: function(chart, args, options) {
const ctx = chart.ctx;
const canvas = chart.canvas;
const chartArea = chart.chartArea;
// Chart background
var gradientBack = canvas.getContext("2d").createLinearGradient(0, 250, 0, 0);
gradientBack.addColorStop(0, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.16, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.17, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.25, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.26, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.5, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.51, "rgba(251,221,221,1)");
gradientBack.addColorStop(1, "rgba(251,221,221,1)");
ctx.fillStyle = gradientBack;
ctx.fillRect(chartArea.left, chartArea.bottom,
chartArea.right - chartArea.left, chartArea.top - chartArea.bottom);
}
};
Than just include it in your Chart options:
plugins: [GradientBgPlugin]
The result should be similar to this JSFiddle.
EDIT
For Reach Charts JS 2, you need small changes in setup. You define plugin this way:
const plugins = [{
beforeDraw: function(chart) {
const ctx = chart.ctx;
const canvas = chart.canvas;
const chartArea = chart.chartArea;
// Chart background
var gradientBack = canvas.getContext("2d").createLinearGradient(0, 250, 0, 0);
gradientBack.addColorStop(0, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.16, "rgba(213,235,248,1)");
gradientBack.addColorStop(0.17, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.25, "rgba(226,245,234,1)");
gradientBack.addColorStop(0.26, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.5, "rgba(252,244,219,1)");
gradientBack.addColorStop(0.51, "rgba(251,221,221,1)");
gradientBack.addColorStop(1, "rgba(251,221,221,1)");
ctx.fillStyle = gradientBack;
ctx.fillRect(chartArea.left, chartArea.bottom,
chartArea.right - chartArea.left, chartArea.top - chartArea.bottom);
}
}];
Than you plug it this way:
<Line data={data} plugins={plugins} />
You can see it working fine on CodeSandbox here.
You can write a custom inline plugin, that draws the colors on the chart Area. In the options section you can put an object with all the sections you want, from where to where and which color they need to be
Example:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [100, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
plugins: {
backgrounds: {
hbars: [{
from: 28,
to: 100,
color: "rgb(195, 230, 195)"
},
{
from: 20,
to: 28,
color: "rgb(230, 220, 195)"
},
{
from: 0,
to: 20,
color: "rgb(230, 195, 195)"
}
]
}
}
},
plugins: [{
id: 'backgrounds',
beforeDraw: (chart, args, options) => {
const {
ctx,
chartArea,
scales: {
y
}
} = chart;
options.hbars.forEach((hBar) => {
ctx.save();
ctx.fillStyle = hBar.color;
ctx.fillRect(chartArea.left, y.getPixelForValue(hBar.from), chartArea.right - chartArea.left, y.getPixelForValue(hBar.to) - y.getPixelForValue(hBar.from));
ctx.restore();
})
}
}]
}
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.2.0/chart.js"></script>
</body>
Detailed explanation can be found here: https://medium.com/#omi10859/alternative-background-lines-in-chartjs-a626ce4d3bcb
We can use annotaion plugin with chartjs to create custom elements.
we can use annotation plugin to do this
import annotationPlugin from "chartjs-plugin-annotation";
import {Chart} from 'chart.js';
Chart.register(annotationPlugin);
this code will add a box to our chart
{
type: 'box', #type of draw
drawTime: 'beforeDraw', #this will decide background or foreground
yMin: 5, #value min on y axis
yMax: 10, #value max on y axis
borderColor: 'rgb(242, 244, 248, 0.9)', #border color of the box
borderWidth: 1, #boarder width for box
backgroundColor: '#F2F4F8', #colour of the box
}
# add option while rendering
const options = {
plugins: {annotation: {annotations: background_annotation}
}
this code render this

Adding a bar (Vertical line) on react-chartjs-2 line chart

I'm using react-chartjs-2 as the chart library for my data visualization.
I need to show one vertical line on a distribution graph. Example:
I have tried to implement as below. I have tried to draw the vertical line by a small math calculation.
Can anyone suggest a better solution than to draw a vertical line on selected X value on the graph?
line_chart_1 = {
datasets: [
{
label: 'My First dataset',
backgroundColor: '#99000022',
borderColor: '#990000',
pointHoverBackgroundColor: '#fff',
borderWidth: 2,
data: data_array,
}
]
}
line_chart_1_opt = {
tooltips: {
enabled: false
},
maintainAspectRatio: false,
legend: {
display: false,
},
scales: {
xAxes: [
{
gridLines: {
drawOnChartArea: false,
},
type: 'linear'
}],
yAxes: [
{
ticks: {
beginAtZero: true,
maxTicksLimit: 5,
stepSize: Math.ceil(250 / 5)
},
}],
},
elements: {
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 4,
hoverBorderWidth: 3,
},
},
title: {
text: 'chart_one'
},
options: {
plugins: {
labels: false
}
}
};
Chart.pluginService.register({
afterDraw: function (chart, easing) {
var margin = 46;
var margin_end = 5;
if (chart.config.options.title.text == 'chart_one') {
var diff = chart.scales['x-axis-0'].end - chart.scales['x-axis-0'].start;
var val = b_amount - chart.scales['x-axis-0'].start;
const ctx = chart.ctx;
const x = (val / diff) * (chart.width - (margin + margin_end)) + margin;
const topY = chart.scales['y-axis-0'].top;
const bottomY = chart.scales['y-axis-0'].bottom;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#ff0000';
ctx.stroke();
}
<Line data={line_chart_1} options={line_chart_1_opt} height={200} />

Values above points - chart.js

I am using this version of ChartJS -> http://www.chartjs.org/samples/latest/charts/line/basic.html
And I'd like to ask you - is there a possibility to add value above the point ?
I think about something like:
^ an example :-)
Was trying to find something using google but unsuccessfully
Thanks in advance,
Yes, there is a possibility :-)
However, there's no built-in functionality for this in ChartJS as of now. You would rather have to create a chart plugin.
ᴘʟᴜɢɪɴ
plugins: [{
afterDatasetsDraw: function(chart) {
var ctx = chart.ctx;
chart.data.datasets.forEach(function(dataset, index) {
var datasetMeta = chart.getDatasetMeta(index);
if (datasetMeta.hidden) return;
datasetMeta.data.forEach(function(point, index) {
var value = dataset.data[index],
x = point.getCenterPoint().x,
y = point.getCenterPoint().y,
radius = point._model.radius,
fontSize = 14,
fontFamily = 'Verdana',
fontColor = 'black',
fontStyle = 'normal';
ctx.save();
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.font = fontStyle + ' ' + fontSize + 'px' + ' ' + fontFamily;
ctx.fillStyle = fontColor;
ctx.fillText(value, x, y - radius - fontSize);
ctx.restore();
});
});
}
}]
* add this followed by your chart options.
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'LINE 1',
data: [3, 1, 4, 2, 5],
backgroundColor: 'rgba(0, 119, 290, 0.5)',
borderColor: 'rgba(0, 119, 290, 0.6)',
fill: false
}, {
label: 'LINE 2',
data: [2, 4, 1, 5, 3],
backgroundColor: 'rgba(233, 30, 99, 0.5)',
borderColor: 'rgba(233, 30, 99, 0.6)',
fill: false
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
max: 7
}
}]
}
},
plugins: [{
afterDatasetsDraw: function(chart) {
var ctx = chart.ctx;
chart.data.datasets.forEach(function(dataset, index) {
var datasetMeta = chart.getDatasetMeta(index);
if (datasetMeta.hidden) return;
datasetMeta.data.forEach(function(point, index) {
var value = dataset.data[index],
x = point.getCenterPoint().x,
y = point.getCenterPoint().y,
radius = point._model.radius,
fontSize = 14,
fontFamily = 'Verdana',
fontColor = 'black',
fontStyle = 'normal';
ctx.save();
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.font = fontStyle + ' ' + fontSize + 'px' + ' ' + fontFamily;
ctx.fillStyle = fontColor;
ctx.fillText(value, x, y - radius - fontSize);
ctx.restore();
});
});
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>

Categories

Resources