Center point labels between ticks (Polar Area Chart JS) - chart.js
I'm using Chart JS in which I have a polar area chart (see image https://imgur.com/XedmesD) I want the point labels to be centered between the ticks. I have found solutions that only seem to work with bar charts that have an X and Y axis by using.
xAxes: [{
gridLines: {
offsetGridLines: true
}
]}
But this does not seem to work when using a polar area chart.
My code is
import React, { Component } from "react";
import Chart from "chart.js";
export default class OrdersFufilledChart extends Component {
OrdersFufilledChart = React.createRef();
componentDidMount() {
const OrdersFufilledChart = this.OrdersFufilledChart.current.getContext(
"2d"
);
new Chart(OrdersFufilledChart, {
type: "polarArea",
data: {
datasets: [
{
data: [342, 323, 333, 352, 361, 299, 272, 423, 425, 400, 382, 363],
backgroundColor: ["#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#ff0931", "#ff0931","#57C5C8","#57C5C8","#57C5C8","#57C5C8","#57C5C8"],
borderWidth: 4,
hoverBorderColor: "white",
}
],
labels: [
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"
],
},
options: {
responsive: true,
plugins: {
datalabels: {
display: false,
},
},
cutoutPercentage: 20,
legend: {
display: false
},
layout: {
padding: 0,
},
scale: {
scaleLabel: {
display: true
},
ticks: {
max: 450,
maxTicksLimit: 1,
display: false,
},
angleLines: {
display: true
},
pointLabels: {
display: true
}
},
}
});
}
render() {
return (
<div>
<canvas
id="OrdersFufilledChart"
ref={this.OrdersFufilledChart}
width={360}
height={360}
/>
</div>
);
}
}
Any insight on how I can do this or pointers in the right direction will be greatly appreciated.
EDIT
I'm looking for something like this with the labels between inbetween.
What about using the datalabels-plugin for that?
I guess you saw my other answer where I used this plugin because your code has many similarities to mine.
I improved my code so it's responsive now. The labels are even animated. I don't share OP's concerns of the other question (offtopic: can somebody correct this genitive here? I know it's wrong...) with cluttered labels in this case because of the small 3-char-labels.
Complete code: https://jsbin.com/hamekugoja/2/edit?js,output
let myChart = new Chart(document.getElementById("pie-chart"), {
type: "polarArea",
data: {
datasets: [{
data: [342, 323, 333, 352, 361, 299, 272, 423, 425, 400, 382, 363],
backgroundColor: ["#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#ff0931", "#ff0931", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8"],
borderWidth: 4,
hoverBorderColor: "white",
}],
labels: [
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"
],
},
options: {
responsive: true,
plugins: {
datalabels: {
formatter: function(value, context) {
return context.chart.data.labels[context.dataIndex];
},
anchor: 'start',
align: 'end',
offset: 0 // Gets updated
},
},
cutoutPercentage: 20,
legend: {
display: false
},
layout: {
padding: 30,
},
scale: {
scaleLabel: {
display: true
},
ticks: {
max: 450,
maxTicksLimit: 1,
display: false,
},
angleLines: {
display: true
},
pointLabels: {
display: false
}
},
onResize: function() {
let width = document.getElementById("pie-chart").width
let padding = myChart.options.layout.padding
myChart.options.plugins.datalabels.offset = width/2-padding
}
}
});
function updateOffset() {
let width = document.getElementById("pie-chart").width
let padding = myChart.options.layout.padding
myChart.options.plugins.datalabels.offset = width/2-padding
myChart.update()
}
updateOffset() //init call after we know the dimensions of the chart
I've been playing around with the docs in chartjs, the only thing I was able to achieve is to center the ticks but the lines of the polar graph are hidden because of something white drawn around the ticks once they are drawn
Polar Charts have a single axis, this means it's a radial chart, there's a single axis th at maps points in the angular and radial directions, these is known as 'radial axes'.
I played with Linear Radial Axis docs from chartjs and was able to center the ticks, hope this may lead to anything helpful in your question
<!DOCTYPE html>
<html>
<head> <meta charset="UTF-8">
<link id='GoogleFontsLink' href='https://fonts.googleapis.com/css?family=Open Sans' rel='stylesheet' type='text/css'><link id='GoogleFontsLink' href='https://fonts.googleapis.com/css?family=Crete Round' rel='stylesheet' type='text/css'><link id='GoogleFontsLink' href='https://fonts.googleapis.com/css?family=Coming Soon' rel='stylesheet' type='text/css'><link id='GoogleFontsLink' href='https://fonts.googleapis.com/css?family=Play' rel='stylesheet' type='text/css'><link id='GoogleFontsLink' href='https://fonts.googleapis.com/css?family=Cabin' rel='stylesheet' type='text/css'>
<script>
WebFontConfig = {
google:
{families: ["Open Sans","Crete Round","Coming Soon","Play","Cabin",]},active: function() {
DrawTheChart(ChartData,ChartOptions,"chart-01","PolarArea")}
};
</script>
<script asyn src="https://livegap.com/charts/js/webfont.js">
</script><script src="https://livegap.com/charts/js/Chart.min.js"></script>
<script>
function DrawTheChart(ChartData,ChartOptions,ChartId,ChartType){
eval('var myLine = new Chart(document.getElementById(ChartId).getContext("2d")).'+ChartType+'(ChartData,ChartOptions);document.getElementById(ChartId).getContext("2d").stroke();')
}
</script>
</head>
<body>
<canvas id="chart-01" width="500" height="500" style="background-color:rgba(255,255,255,1.00);border-radius:0px;width:500px;height:500px;padding-left:0px;padding-right:0px;padding-top:0px;padding-bottom:0px"></canvas>
<script> function MoreChartOptions(){} var ChartData = [{value :65,
color:'rgba(52,152,219,1)',title:'enero'},{value :8,color:'rgba(46,204,113,1)',title:'febrero'},{value :90,color:'rgba(166,107,190,1)',title:'marzo'},{value :81,color:'rgba(241,196,15,1)',title:'abril'},{value :56,color:'rgba(230,126,34,1)',title:'mayo'},{value :55,color:'rgba(192,58,43,1)',title:'junio'},{value :40,color:'rgba(141,68,173,1)',title:'julio'},];ChartOptions= {decimalSeparator:".",thousandSeparator:",",spaceLeft:12,spaceRight:12,spaceTop:12,spaceBottom:12,scaleLabel:"<%=value+''%>",yAxisMinimumInterval:'none',scaleShowLabels:false,scaleShowLine:false,scaleLineStyle:"solid",scaleLineWidth:1,scaleLineColor:"rgba(0,0,0,0.6)",scaleOverlay :false,scaleOverride :false,scaleSteps:10,scaleStepWidth:10,scaleStartValue:0,inGraphDataShow:true,inGraphDataTmpl:'<%=v2%>',inGraphDataFontFamily:"'Crete Round'",inGraphDataFontStyle:"normal normal",inGraphDataFontColor:"rgba(51,51,51,1)",inGraphDataFontSize:15,inGraphDataPaddingX:0,inGraphDataPaddingY:0,inGraphDataAlign:"center",inGraphDataVAlign:"middle",inGraphDataXPosition:2,inGraphDataYPosition:3,inGraphDataAnglePosition:2,inGraphDataRadiusPosition:3,inGraphDataRotate:0,inGraphDataPaddingAngle:0,inGraphDataPaddingRadius:15, inGraphDataBorders:false,inGraphDataBordersXSpace:1,inGraphDataBordersYSpace:1,inGraphDataBordersWidth:1,inGraphDataBordersStyle:"solid",inGraphDataBordersColor:"rgba(0,0,0,1)",legend:true,maxLegendCols:5,legendBlockSize:20,legendFillColor:'rgba(255,255,255,0.00)',legendColorIndicatorStrokeWidth:1,legendPosX:-2,legendPosY:4,legendXPadding:0,legendYPadding:0,legendBorders:false,legendBordersWidth:1,legendBordersStyle:"solid",legendBordersColors:"rgba(102,102,102,1)",legendBordersSpaceBefore:5,legendBordersSpaceLeft:5,legendBordersSpaceRight:5,legendBordersSpaceAfter:5,legendSpaceBeforeText:5,legendSpaceLeftText:5,legendSpaceRightText:5,legendSpaceAfterText:5,legendSpaceBetweenBoxAndText:5,legendSpaceBetweenTextHorizontal:5,legendSpaceBetweenTextVertical:5,legendFontFamily:"'Cabin'",legendFontStyle:"normal normal",legendFontColor:"rgba(0,0,0,1)",legendFontSize:15,showYAxisMin:false,rotateLabels:"smart",xAxisBottom:true,yAxisLeft:true,yAxisRight:false,graphTitleSpaceBefore:5,graphTitleSpaceAfter:5, graphTitleBorders:false,graphTitleBordersXSpace:1,graphTitleBordersYSpace:1,graphTitleBordersWidth:1,graphTitleBordersStyle:"solid",graphTitleBordersColor:"rgba(0,0,0,1)",graphTitle : "Gráfico Título",graphTitleFontFamily:"'Coming Soon'",graphTitleFontStyle:"normal normal",graphTitleFontColor:"rgba(52,152,219,1)",graphTitleFontSize:33,graphSubTitleSpaceBefore:-8,graphSubTitleSpaceAfter:3, graphSubTitleBorders:false,graphSubTitleBordersXSpace:1,graphSubTitleBordersYSpace:1,graphSubTitleBordersWidth:1,graphSubTitleBordersStyle:"solid",graphSubTitleBordersColor:"rgba(0,0,0,1)",graphSubTitle : "Añadir título sub aquí",graphSubTitleFontFamily:"'Play'",graphSubTitleFontStyle:"normal normal",graphSubTitleFontColor:"rgba(10,10,10,1)",graphSubTitleFontSize:14,scaleFontFamily:"'Open Sans'",scaleFontStyle:"normal normal",scaleFontColor:"rgba(0,0,0,1)",scaleFontSize:12,pointLabelFontFamily:"'Open Sans'",pointLabelFontStyle:"normal normal",pointLabelFontColor:"rgba(102,102,102,1)",pointLabelFontSize:12,angleShowLineOut:true,angleLineStyle:"solid",angleLineWidth:1,angleLineColor:"rgba(0,0,0,0.1)",percentageInnerCutout:50,scaleShowGridLines:true,scaleGridLineStyle:"solid",scaleGridLineWidth:1,scaleGridLineColor:"rgba(0,0,0,0.1)",scaleXGridLinesStep:1,scaleYGridLinesStep:3,segmentShowStroke:true,segmentStrokeStyle:"solid",segmentStrokeWidth:2,segmentStrokeColor:"rgba(255,255,255,1.00)",datasetStroke:true,datasetFill : true,datasetStrokeStyle:"solid",datasetStrokeWidth:2,bezierCurve:true,bezierCurveTension :0.4,pointDotStrokeStyle:"solid",pointDotStrokeWidth : 1,pointDotRadius : 3,pointDot : true,scaleTickSizeBottom:5,scaleTickSizeTop:5,scaleTickSizeLeft:5,scaleTickSizeRight:5,graphMin:0,barShowStroke : false,barBorderRadius:0,barStrokeStyle:"solid",barStrokeWidth:1,barValueSpacing:15,barDatasetSpacing:0,scaleShowLabelBackdrop :true,scaleBackdropColor:'rgba(255,255,255,0.75)',scaleBackdropPaddingX :2,scaleBackdropPaddingY :2,animation : true,onAnimationComplete : function(){MoreChartOptions()}};
DrawTheChart(ChartData,ChartOptions,"chart-01","PolarArea");</script></body></html>
Check out what I did on ticks:{}, and angeLines:{},
You might want to take a look at the docs, anyway tbh I think you'll have to go into New Axes and extend your polar chart to fulfill your needs.
Do you mind trying to use another chart generator? Try this
Related
Fill gap between stacked bars in chart.js
I'm currently using chart.js with Vue 2 and I'm facing a problem when using border-radius with stacked bars. I want to have a border-top radius but when doing that I get a "gap" between the border that was created and the bar above. Is there any option that can fill that empty space? Current behaviour Expected behaviour These are the current options I'm using for the graph. options: { responsive: true, lineTension: 1, plugins: { legend: { position: 'bottom', // prevent filtering using labels 'onClick' : function (evt, item, legend) { return; }, labels: { usePointStyle: 'circle', }, } }, elements: { bar: { borderRadius: { topLeft: 4.6, topRight: 4.6, }, } }, scales: { y: { stacked: true, ticks: { maxTicksLimit: 6, callback: function(value, index, ticks) { return value + ' min'; } }, }, x: { stacked: true, grid: { color: "rgba(0, 0, 0, 0)", } } } }
What you need it is not configurable by any options. Nevertheless you can use a plugin to change the base of the bar to draw, taking care of the border radius. EDIT: I have found a specific option in bar element, base, which should address the use case. See snippet: const ctx = document.getElementById("myChart"); // not used but leave it const plugin = { id: 'fillGaps', beforeDatasetDraw(chart, args) { if (args.index > 0) { args.meta.data.forEach(function(item){ const pre = item.base; item.base += 12; }); } }, }; // const myChart = new Chart(ctx, { type: 'bar', data: { labels: ['January', 'Fabruary', 'March', 'April', 'May', 'June', 'July'], datasets: [{ label: 'user 1 online', data: [50, 35, 45, 47, 10, 3, 27], backgroundColor: 'rgba(40, 139, 170, 1)', borderWidth: 0, borderSkipped: 'start', base: 0 }, { label: 'user 2 online', data: [50, 35, 45, 47, 10, 3, 27], backgroundColor: 'orange', borderWidth: 0, borderSkipped: 'start', base: 0 }] }, options: { elements: { bar: { borderRadius: { topLeft: 12, topRight: 12, bottomLeft: 12, bottomRight: 12 }, } }, scales: { y: { stacked: true, }, x: { stacked: true, } } } }); .myChartDiv { max-width: 600px; max-height: 400px; } <script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script> <html> <body> <div class="myChartDiv"> <canvas id="myChart" width="600" height="400"/> </div> </body> </html>
Chartjs Polar Area Chart - Data labels shown don't rotate with startAngle
I am setting the startAngle on my polar chart so the first category starts on the -180 degrees. But I can't figure out why the data point labels don't correspondingly adjust and rotate. As a result, they show up incorrectly against the wrong data. As you can see in the image, Question 6 still appears where Question 1 should be. The tooltips on each section do appear correctly. Note: When I use the datalabels plugin, it does show the label correctly. But I am not using it because it does not wrap the labels and also it cuts off the labels if they become too big. In addition I had responsiveness problems with it. So please suggest a solution without that plugin if possible. Thank you very much for helping me out. const mydata = { labels: [ 'Question1', 'Question2', 'Question3', 'Question4', 'Question5', 'Question6' ], datasets: [{ label: 'Data labels don't move', data: [5, 8, 6, 6, 7, 8], backgroundColor: [ 'rgb(255, 99, 132)', 'rgb(75, 192, 192)', 'rgb(255, 205, 86)', 'rgb(201, 203, 207)', 'rgb(255, 99, 132)', 'rgb(201, 203, 207)' ] }] }; var myChart = new Chart('mychartId'), { type: "polarArea", data: mydata, options: { responsive: true, cutoutPercentage: 20, startAngle: -1 * Math.PI, legend: { display: false }, layout: { padding: 20 }, scale: { ticks: { max: 10, beginAtZero: true, min: 1, stepSize: 1, display: false }, angleLines: { display: false }, pointLabels: { display: true } } } } sample image showing the problem
Update to V3, there they do turn with the chart if you adjust the startAngle var options = { type: 'polarArea', data: { labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], datasets: [{ label: '# of Votes', data: [2, 9, 3, 5, 2, 3], borderWidth: 1 }] }, options: { scales: { r: { startAngle: 180, ticks: { display: false }, pointLabels: { display: true } } } } } 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.6.0/chart.js"></script> </body> V3 has some breaking changes over V2, for all of them you can read the migration guide
ChartJS horizontal bar with numbers on both scales
I have an issue with Chartjs bar chart. It doesn't display numeric values on both axis. I hope you can give an advice how to resolve the issue. I have the following data structures when both scaled are numeric: {"x": 86, "y": 20}, {"x": 255, "y": 21}, {"x": 207, "y": 34}, The y axis is not a category but a number. Here's how my chart looks like: As you can see, there are no values on y axis. Y axis is not even show and the chart looks more like a stacked chart. Here's how configuration looks like: config: { type: "bar", data: { datasets: [], }, plugins: [], options: { responsive: true, indexAxis: "y", elements: { bar: { borderWidth: 2, }, }, }, scales: { y: { position: "left", ticks: { color: "blue", font: 24, }, }, }, },
This is because chart.js still thinks it needs to be a category scale so you will need to override that. If you do that it shows up fine. A second thing, to make the ticks bigger you need to specify the size in the font object, the font does not accept a number. For all font properties you can specify there you can read the docs here var options = { type: 'bar', data: { labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], datasets: [{ label: '# of Votes', data: [{ "x": 86, "y": 20 }, { "x": 255, "y": 21 }, { "x": 207, "y": 34 } ], backgroundColor: 'pink' }] }, options: { indexAxis: "y", scales: { y: { type: 'linear', ticks: { color: "blue", font: { size: 24 }, }, } } } } 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.6.0/chart.js"></script> </body>
gap between half doughnut chart and container div
I'm trying to build a doughnut chart with chart.js but the chart container is bigger than the chart canvas and it makes it harder to design stuff around it... is there any option to make the chart and the container the same height and width? settings: var option = { rotation: 1 * Math.PI, circumference: 1 * Math.PI, responsive: true, aspectRatio:2, title: { display: false }, legend: { display: false }, scales: { xAxes: [ { gridLines: { drawBorder: false, display: false, }, ticks: { display: false, }, }, ], yAxes: [ { gridLines: { drawBorder: false, display: false, }, ticks: { display: false, }, }, ], } }; Code Pen: https://codepen.io/ronmara/pen/vYGeJyo You can see there is a little gap between the left, right, and bottom border of the div.
It's a bit of a hacky solution, but setting layout.padding to -10 fits your doughnut more neatly in your container: var data = { labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"], datasets: [ { label: "Dataset #1", backgroundColor: "rgba(255,99,132,0.2)", borderColor: "rgba(255,99,132,1)", borderWidth: 2, hoverBackgroundColor: "rgba(255,99,132,0.4)", hoverBorderColor: "rgba(255,99,132,1)", data: [65, 59, 20, 81, 56, 55, 40] } ] }; var option = { rotation: 1 * Math.PI, circumference: 1 * Math.PI, responsive: true, aspectRatio: 2, title: { display: false }, legend: { display: false }, layout: { padding: -10 }, scales: { xAxes: [ { gridLines: { drawBorder: false, display: false }, ticks: { display: false } } ], yAxes: [ { gridLines: { drawBorder: false, display: false }, ticks: { display: false } } ] } }; Chart.Doughnut("chart_0", { options: option, data: data }); body { background: white; padding: 16px; } canvas { border: 1px dotted red; } <script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3"></script> <div class="chart-container" style="position: relative; height:16vh; width:32vh"> <canvas id="chart_0"></canvas> </div>
I got it centered by removing the inline styles and adding them to the class attached to the div. I also added the layout.padding into your options. layout: { padding: { left: 0, top: 10, right: 10, bottom: 0 }}, Adding codepen for reference. https://codepen.io/robert9111/pen/abNVxWY
Chartjs change grid line color
First I don't know what's it called. But how do you change its color from gray to white? Or is it even possibe?
It is possible to either remove the grid lines or have them display in a different color. In both options.scales.xAxes and options.scales.yAxes you can add gridLines: { display: false , color: "#FFFFFF" }, (obviously you do not need to assign a colour if you are not disaplying them) var 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(231,233,237)' }; var randomScalingFactor = function() { return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100); } var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; var config = { type: 'line', data: { labels: ["January", "February", "March", "April", "May", "June", "July"], datasets: [{ label: "My First dataset", backgroundColor: chartColors.red, borderColor: chartColors.red, data: [ randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor() ], fill: false, }, { label: "My Second dataset", fill: false, backgroundColor: chartColors.blue, borderColor: chartColors.blue, data: [ randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor() ], }] }, options: { responsive: true, title: { display: true, text: 'Chart.js Line Chart' }, tooltips: { mode: 'label', }, hover: { mode: 'nearest', intersect: true }, scales: { xAxes: [{ display: true, gridLines: { display: false }, scaleLabel: { display: true, labelString: 'Month' } }], yAxes: [{ display: true, gridLines: { display: false }, scaleLabel: { display: true, labelString: 'Value' } }] } } }; var ctx = document.getElementById("canvas").getContext("2d"); window.myLine = new Chart(ctx, config); <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.1/Chart.js"></script> <div style="width:100%;"> <canvas id="canvas"></canvas> </div>
Since v3 the scales have been changed so if you want your gridlines to have a different color you will need to configure it in options.scales[scaleID].grid.color: var 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: { scales: { y: { grid: { color: 'white' } }, x: { grid: { color: 'red' } } } } } 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.6.0/chart.js"></script> </body>
Try this: options: { scales: { x: { display: true, grid: { display: false }, }, y: { display: true, grid: { display: false }, } } }