I've been using ChartJS with PrimeNG, in Angular. Need to make a doughnut chart with i believe one dataset. I need to make it so each value has a different thickness, like this
So far I've tried a lot of things and read a lot of ChartJS documentation on Doughnut charts, but none of the options have helped me.
Here's how I implement my chart in HTML
<p-chart type="doughnut" [data]="donutData" [options]="donutChartOptions" class="h-10 my-4"></p-chart>
And here's the .ts to it
this.donutData = {
labels: ['A', 'B', 'C'],
datasets: [
{
data: [300, 50, 100],
backgroundColor: ['#F36F56', '#FFC300', '#B8A3FF'],
hoverBackgroundColor: ['#F36F56', '#FFC300', '#B8A3FF'],
},
],
};
this.donutChartOptions = {
cutout: 50,
plugins: {
legend: {
display: false,
labels: {
color: '#ebedef',
},
},
},
};
Here you can find the answer of your question: https://github.com/chartjs/Chart.js/issues/6195
I transferred the answer of "ex47" to chart.js 3
I put the constant "data" into the html file just to have less double code, it should better be in the javascript file.
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<script>
const data = {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)"
],
borderWidth: 1
}
]
}
</script>
<style>
#chartWrapper {
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<div id="chartWrapper">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
</body>
<script src="myChart.js"></script>
</html>
myChart.js
var thickness = {
id: "thickness",
beforeDraw: function (chart, options) {
let thickness = chart.options.plugins.thickness.thickness;
thickness.forEach((item,index) => {
chart.getDatasetMeta(0).data[index].innerRadius = item[0];
chart.getDatasetMeta(0).data[index].outerRadius = item[1];
});
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: "doughnut",
plugins: [thickness],
data: data,
options: {
plugins: {
thickness: {
thickness: [[100,130],[80,150],[70,160],[100,130],[100,130],[100,130]],
}
},
}
});
"Spirit04eK"'s solution sets the thickness in descending order of the magnitude of the value
myChart.js
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'doughnut',
plugins: [
{
beforeDraw: function (chart) {
const datasetMeta = chart.getDatasetMeta(0);
const innerRadius = datasetMeta.controller.innerRadius;
const outerRadius = datasetMeta.controller.outerRadius;
const heightOfItem = outerRadius - innerRadius;
const countOfData = chart.getDatasetMeta(0).data.length;
const additionalRadius = Math.floor(heightOfItem / countOfData);
const weightsMap = datasetMeta.data
.map(v => v.circumference)
.sort((a, b) => a - b)
.reduce((a, c, ci) => {
a.set(c, ci + 1);
return a;
}, new Map());
datasetMeta.data.forEach(dataItem => {
const weight = weightsMap.get(dataItem.circumference);
dataItem.outerRadius = innerRadius + additionalRadius * weight;
});
}
}
],
data: data,
options: {
layout: {
padding: 10,
},
plugins: {
legend: false,
datalabels: {
display: false
},
},
maintainAspectRatio: false,
responsive: true,
}
});
Related
I am trying to use formatting in Chart.js. I've configured the imports correctly, but it still doesn't display what I want
It doesn't work on my local pc. I uploaded the same code to codepen and it didn't work either. You can verify it here
var donutEl = document.getElementById("donut").getContext("2d");
var data = [4, 9, 5, 2];
var pieChart = new Chart(donutEl, {
type: 'doughnut',
data: {
datasets: [
{
data: [10, 20, 15, 5, 50],
backgroundColor: [ 'rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)', 'rgb(54, 162, 235)', ],
},
],
labels: ['Red', 'Orange', 'Yellow', 'Green', 'Blue'],
},
options: {
plugins: {
datalabels: {
formatter: (value) => {
return value + '%';
}
}
}
}
})
Any ideas what am I doing wrong? Thanks
As described here, you need to register the plugin:
Chart.register(ChartDataLabels);
Live example:
Chart.register(ChartDataLabels);
const donutEl = document.getElementById("donut").getContext("2d");
const data = [4, 9, 5, 2];
const pieChart = new Chart(donutEl, {
type: 'doughnut',
data: {
datasets: [{
data: [10, 20, 15, 5, 50],
backgroundColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)', 'rgb(54, 162, 235)', ],
}, ],
labels: ['Red', 'Orange', 'Yellow', 'Green', 'Blue'],
},
options: {
plugins: {
datalabels: {
formatter: (value) => {
return value + '%';
}
}
}
}
})
<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.min.js"></script>
<div class="flexWrapper">
<canvas id="donut" width="400" height="400"></canvas>
</div>
I am having some trouble with my chartjs code. I have a date feed that send data to the charts seen below. While score, and day_7_average worked fine when converting to a list. I am having trouble the dates. the data format I receive is in the "const test" variable and I need it in the "const dates" variable. Based on the nature of the project I can not type them out every time. What is the best way of fixing this problem? thanks.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Sentiment</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.js"></script>
</head>
<style>
.bar { fill: steelblue; }
body { background-color: #1c142c; }
</style>
<body>
<div>
<h1 style="font: 200; color: white;">What are people saying on social media?</h1>
<canvas id="canvas""></canvas>
</div>
</body>
<script>
var ctx = document.getElementById("canvas").getContext('2d');
const test = ['2020-12-24', '2020-12-25', '2020-12-26', '2020-12-27', '2020-12-28', '2020-12-29', '2020-12-30', '2020-12-31']
const dates = ['2020-12-24','2020-12-25','2020-12-26','2020-12-27','2020-12-28','2020-12-29','20201-12-30','2020-12-31']
const score = [-2, -40, 81, -31, 34, -35, -24, -30]
const day_7_average = [0, -6, 3, -2, 5, 5, 0, -7]
window.chartColors = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
const colours = score.map((value) => value < 0 ? 'rgb(255, 99, 132)' : 'rgb(75, 192, 192)');
var chartData = {
labels: dates,
datasets: [{
type: 'line',
label: '7 day average',
backgroundColor: 'rgb(201, 203, 207)',
borderColor: 'rgb(201, 203, 207)',
borderWidth: 2,
fill: false,
data: day_7_average,
},
{
type: 'bar',
label: 'Sentiment Score',
backgroundColor: colours,
data: score
}]
};
window.onload = function() {
window.myMixedChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
}
}
});
};
Well... it may be a sloppy workaround but try this:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Sentiment</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.js"></script>
</head>
<style>
.bar { fill: steelblue; }
body { background-color: #1c142c; }
</style>
<body>
<div>
<h1 style="font: 200; color: white;">What are people saying on social media?</h1>
<canvas id="canvas"></canvas>
</div>
</body>
<script>
var ctx = document.getElementById("canvas").getContext('2d');
const test = [''2020-12-24'',
''2020-12-25'',
''2020-12-26'',
''2020-12-27'',
''2020-12-28'',
''2020-12-29'',
''2020-12-30'',
''2020-12-31''];
var i;
dates_tmp = [];
for (i = 0; i < test.length; i++) {
dates_tmp.push(String(test[i].replaceAll("'", "")));
}}
const dates = dates_tmp;
const score = [-2, -40, 81, -31, 34, -35, -24, -30]
const day_7_average = [0, -6, 3, -2, 5, 5, 0, -7]
window.chartColors = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
const colours = score.map((value) => value < 0 ? 'rgb(255, 99, 132)' : 'rgb(75, 192, 192)');
var chartData = {
labels: dates,
datasets: [{
type: 'line',
label: '7 day average',
backgroundColor: 'rgb(201, 203, 207)',
borderColor: 'rgb(201, 203, 207)',
borderWidth: 2,
fill: false,
data: day_7_average,
},
{
type: 'bar',
label: 'Sentiment Score',
backgroundColor: colours,
data: score
}]
};
window.onload = function() {
window.myMixedChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
}
}
});
};
</script>
</html>
( Oh and by the way: You've got an unexpected " in line 16 )
I was able to create this doughnut chart that displays data. However, now that I look at it, I would like add the number value of the foods (100,200,300) below, on a second line, instead of having next to the food item itself. Is there a way to do this? I was thinking that since this is a nested array, looping through it may work? Any thoughts?
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
label1: [["Pizza: 100"], ["Hot Dogs: 200"], ["Burgers:300"]],
datasets: [{
label: '# of Votes',
data: [12, 19, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)'
],
borderWidth: 1
}]
},
options: {
tooltips: {
callbacks: {
title: function(tooltipItem, data, label1, label2) {
return data ['label1'][tooltipItem[0]['index']];
},
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']];
},
afterLabel: function(tooltipItem, data) {
var dataset = data['datasets'][0];
var percent = Math.round((dataset['data'][tooltipItem['index']] / dataset["_meta"][0]['total']) * 100)
return '(' + percent + '%)';
}
},
backgroundColor: '#FFF',
titleFontSize: 16,
titleFontColor: '#0066ff',
bodyFontColor: '#000',
bodyFontSize: 14,
displayColors: false
}
}
});
<div>
<canvas id="myChart" height="100"></canvas>
<div id="chartjs-tooltip">
<table></table>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js">
</script>
I'm using the last version of chart.js and I want to add a shadow to each bar
Here's an example of code
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)'],
borderColor: ['rgba(255,99,132,1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)'],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>
This will work for the line chart.
[Edited...]
Chart.types.Line.extend({
name: "LineAlt",
initialize: function () {
Chart.types.Line.prototype.initialize.apply(this, arguments);
var ctx = this.chart.ctx;
var originalStroke = ctx.stroke;
ctx.stroke = function () {
ctx.save();
ctx.shadowColor = '#000';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 8;
ctx.shadowOffsetY = 8;
originalStroke.apply(this, arguments)
ctx.restore();
}
}
});
var data = {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
fillColor: "rgba(255, 99, 132, 0.2)",
strokeColor: "rgba(54, 162, 235, 0.2)",
pointColor: "rgba(255, 206, 86, 0.2)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(75, 192, 192, 0.2)",
data: [12, 19, 3, 5, 2, 3]
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
var canvas = new Chart(ctx).LineAlt(data, {
datasetFill: false
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<canvas id="myChart" width="600" height="300"></canvas>
Appreciate if useful
Based on this answer, I created a runnable code snippet that illustrates how to create bars with shadows.
const dataset = [40, 80, 50, 60, 70];
const offset = 8;
Chart.pluginService.register({
afterUpdate: function(chart) {
var metaData = chart.getDatasetMeta(0).data;
for (var i = 0; i < metaData.length; i++) {
var model = metaData[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
}
});
var data = {
labels: ["A", "B", "C", "D", "E"],
datasets: [{
backgroundColor: [
'rgba(255, 99, 132)',
'rgba(255, 206, 86)',
'rgba(54, 162, 235)',
'rgba(75, 192, 192)',
'rgba(153, 102, 255)'
],
borderWidth: 1,
data: dataset,
xAxisID: "bar-x-axis1",
categoryPercentage: 0.5,
barPercentage: 0.5,
},
{
backgroundColor: 'rgba(0, 0, 0, 0.2)',
data: dataset.map(v => v + offset),
xAxisID: "bar-x-axis2",
categoryPercentage: 0.5,
barPercentage: 0.5
}
]
};
var options = {
legend: {
display: false
},
tooltips: {
enabled: false
},
scales: {
xAxes: [
{
id: "bar-x-axis2"
},
{
id: "bar-x-axis1",
offset: true,
display: false
}
],
yAxes: [{
id: "bar-y-axis1",
ticks: {
beginAtZero: true,
stepSize: 50
}
}]
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="60"></canvas>
I'm making a chart with chart.js and I'm trying to figure out how I can change the label/legend styling.
I want to remove the rectangle part and instead use a circle. I've read that you can make your custom legend (using legendCallback), but for the life of me I cannot figure out how to do it. This is how my chart looks now - image.
This is my HTML:
<div class="container">
<canvas id="myChart"></canvas>
</div>
And this is my JS:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: 'Link One',
data: [1, 2, 3, 2, 1, 1.5, 1],
backgroundColor: [
'#D3E4F3'
],
borderColor: [
'#D3E4F3',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
legend: {
display: true,
position: 'bottom',
labels: {
fontColor: '#333',
}
}
}
});
I'm new to JS in general, so please be as specific as possible with your answers. Thank you so much!
No need to use legendCallback function. You can set usePointStyle = true to turn that rectangle into a circle.
Chart.defaults.global.legend.labels.usePointStyle = true;
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: 'Link One',
data: [1, 2, 3, 2, 1, 1.5, 1],
backgroundColor: [
'#D3E4F3'
],
borderColor: [
'#D3E4F3',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
legend: {
display: true,
position: 'bottom',
labels: {
fontColor: '#333'
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="container">
<canvas id="myChart"></canvas>
</div>
for angular4-chart.js you could use the options attribute like so:
options = {
legend:{
display: true,
labels: {
usePointStyle: true,
}
}
}
Step 1:
Change options to this:
options: {
legend: {
display: false,
}
}
Step 2:
Append to your canvas this code (just after canvas):
<div id='chartjsLegend' class='chartjsLegend'></div> //Or prepend to show the legend at top, if you append then it will show to bottom.
Step 3:
Generate this legend instead of default with this (just after mychart):
document.getElementById('chartjsLegend').innerHTML = myChart.generateLegend();
Step 4:
Make css so it generates as circle:
.chartjsLegend li span {
display: inline-block;
width: 12px;
height: 12px;
margin-right: 5px;
border-radius: 25px;
}
Step 5:
Change css with what ever you feel like should be better.
Time for some chimichangas now.
Use usePointStyle:true
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: 'Link One',
data: [1, 2, 3, 2, 1, 1.5, 1],
backgroundColor: [
'#D3E4F3'
],
borderColor: [
'#D3E4F3',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
legend: {
display: true,
position: 'bottom',
labels: {
fontColor: '#333',
usePointStyle:true
}
}
}
});
Additional information on #GRUNT 's answer
I assign usePointStyle inside legend.labels not what #GRUNT did Chart.defaults.global.legend.labels.usePointStyle = true;
This is useful when you are using react
legend: {
labels: {
usePointStyle: true,
},
}
more info here
Display point style on legend in chart.js
add this in your options
legend: {
display: true,
position: 'bottom',
labels: {
boxWidth: 9,
fontColor: '#474747',
fontFamily: '6px Montserrat',
},
},
for example :
this.testChart = new Chart('testPie', {
type: 'doughnut',
data: {
labels: [ 'Success','Failure','Aborted'],
datasets: [
{
data: [],
backgroundColor: [ '#45D78F', '#F58220','#FFD403'],
},
],
},
options: {
maintainAspectRatio: false,
cutoutPercentage: 50, // for thikness of doughnut
title: {
display: false,
text: 'Runs',
fontSize: 14,
fontFamily: 'Roboto',
fontColor: '#474747',
},
legend: {
display: true,
position: 'bottom',
labels: {
boxWidth: 9,
fontColor: '#474747',
fontFamily: '6px Montserrat',
},
},
},
});