Have text displayed instead of numerical values on y axis - javascript

Is it possible to display text instead of numerical values in the y axis of a line graph with Chart.JS?
Say that we have, for example, the following text-to-value mapping.
0 = "sedentary"
1 = "under-active"
2 = "active"
....
How can we display the words "sedentary", "under-active", etc instead of the numerical values in the following graph:

Yes, it is possible, and you can achieve that using the userCallback function for y-axis ticks.
var mapText = ['sedentary', 'under-active', 'active', 'inactive'];
var chart = new Chart(canvas, {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April'],
datasets: [{
label: 'Statistics',
data: [3, 1, 2, 0],
backgroundColor: 'rgba(0, 119, 204, 0.1)',
borderColor: 'rgba(0, 119, 204, 0.8)',
borderWidth: 1,
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
maxTicksLimit: 4, //set as the 'mapText' array length
stepSize: 1,
userCallback: function(t, i) {
return mapText[mapText.length - (i + 1)];
}
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas"></canvas>

Related

Chartjs bar min, max and avarage value

Hi I have a chart with chartjs, which inserts between min, max, average values, with a bar type chart.
So far, everything is fine, the values are entered, what I want to do is that the bars of the graph are positioned starting from their min on the y axis up to the maximum on the y axis, I do not want the bar to start from the value 0.
dataset = {
labels: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'],
datasets: [{
label: 'min',
borderWidth: 4,
borderColor: "#ef4931",
backgroundColor: "#ef4931",
borderJoinStyle: 'miter',
pointHitRadius: 10,
data: data[1],
fill: false,
},
{
label: 'avg',
borderWidth: 4,
borderColor: "#ef4931",
backgroundColor: "#ef4931",
borderJoinStyle: 'miter',
pointHitRadius: 10,
data: data[0],
fill: "-1",
},
{
label: 'max',
borderWidth: 4,
borderColor: "#ef4931",
backgroundColor: "#ef4931",
borderJoinStyle: 'miter',
pointHitRadius: 10,
data: data[2],
fill: "-1",
}
]
};
options = {
legend: {
display: false,
},
title: {
display: true,
position: 'bottom',
fontSize: 14
},
tooltips: {
mode: 'index',
intersect: false,
titleFontStyle: "bold",
titleFontColor: "rgba(255, 255, 255, 1)",
bodyFontStyle: "normal",
bodyFontColor: "rgba(255, 255, 255, 1)",
backgroundColor: "rgba(102, 102, 102, 1)",
borderWidth: 1,
bodySpacing: 5,
xPadding: 15,
yPadding: 15,
displayColors: false,
callbacks: {
title: function(item, data) {
var title = "";
title += item[0].xLabel;
return title;
}
}
},
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
stacked: true,
barThickness: 10,
}],
yAxes: [{
stacked: true,
display: true,
scaleLabel: {
display: true,
fontSize: 14,
fontStyle: "bold",
},
ticks: {
callback: function(value, index, values) {
return parseInt(value) + " bpm";
},
}
}]
},
animation: {
duration: 1000,
easing: "easeInOutQuad"
}
};
myChart.config.data = dataset;
myChart.options = options;
myChart.config.type = "bar";
myChart.update();
in your y axes config you can add the prop suggestedMin or min between the stacked and display prop. With this the scale will start at that number, here you can put in the value of the lowest bar.
SuggestedMin will go lower if there is a bar with a lower value, if you use min if will use that as a final so if you have a bar with a lower value it wont get shown.
You can combine "floating bars" and "stacked bar chart". See https://codepen.io/fantasyzer/pen/KKaqgoM for an example. Note that the data of each bar is given as an array [Ybegin,Yend]. If you set stackable to false for the y scale the values are to be given as absolute:
datasets: [
{
data: [
[10,12],
[20,25],
[15,25],
[25,28],
...
Ref:
https://www.chartjs.org/docs/latest/samples/bar/floating.html, https://www.chartjs.org/docs/latest/samples/bar/stacked.html

Legend not displaying on Line or Bar chart - React-Chartjs-2

I am having some difficulties getting the legend to display on several of my graphs in my react dashboard.
I am using React-Chartjs-2 . The legends were working originally, then I tested turning legends off in the Chart.default properties and when I tried to turn it back on, they did not reappear.
My global Chart settings are as follows:
// React-Chartjs-2 Global Styling
defaults.global.elements.point.radius = 1;
defaults.global.elements.line.tension = 0.1;
defaults.global.elements.point.hoverRadius = 10;
defaults.global.elements.point.hitRadius = 12;
// Font
defaults.global.defaultFontSize = 12;
defaults.global.defaultFontColor = "#838383";
// Legend
defaults.global.legend.display = true;
defaults.global.legend.align = "start";
defaults.global.legend.position = "bottom";
defaults.global.legend.labels = {
padding: 30,
boxWidth: 15,
};
My local chart properties for my Line, Bar and Doughnut charts all follow a similar layout, being:
<Line
data={props.graph.data}
height={300}
options={{
maintainAspectRatio: false,
legend: {
display: true,
},
scales: {
xAxes: [{
gridLines: {
display: false
}
}],
yAxes: [{
gridLines: {
drawBorder: false,
},
ticks: {
beginAtZero:true,
// Include a kwh sign in the ticks
callback: function(value, index, values) {
return value + 'kWh';
}
},
}]
}
}}
/>
As you can see, Legends are turned on in both global and local settings.
Currently, only the doughnut chart is displaying it's legend. Toggling the display:true value only shifts the bottom of the Line/Bar chart up and down a small amount.
Anybody encountered a similar issue?
It looks like the defaults can't handle being passed an object, if you define the defaults for the legend label padding and boxWidth separately then it will render your legend.
Normal example but problem was the same as if you would use react wrapper:
const defaults = Chart.defaults;
defaults.global.elements.point.radius = 1;
defaults.global.elements.line.tension = 0.1;
defaults.global.elements.point.hoverRadius = 10;
defaults.global.elements.point.hitRadius = 12;
// Font
defaults.global.defaultFontSize = 12;
defaults.global.defaultFontColor = "#838383";
// Legend
defaults.global.legend.display = true;
defaults.global.legend.align = "start";
defaults.global.legend.position = "bottom";
defaults.global.legend.labels.padding = 30;
defaults.global.legend.labels.boxWidth = 15;
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false
}
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
canvas {
background-color : #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js" integrity="sha512-hZf9Qhp3rlDJBvAKvmiG+goaaKRZA6LKUO35oK6EsM0/kjPK32Yw7URqrq3Q+Nvbbt8Usss+IekL7CRn83dYmw==" crossorigin="anonymous"></script>
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
</body>
Already answer has been given even though, I would like to give alternative solution without defaults namespace options.
We can achieve it with plugins namespace in reactjs.
<Line
data={{
labels: ["1", "2", "3", "4", "5", "6"],
datasets: [
{
label: "Primary kVA",
data: [6, 17, 12, 19, 10, 55, 5, 22, 3, 100, 200, 350],
fill: false,
backgroundColor: "rgb(255, 99, 132)",
borderColor: "rgba(255, 99, 132, 0.2)",
},
{
label: "Redundant kVA",
data: [12, 23, 33, 55, 22, 300, 100, 200, 350],
fill: false,
backgroundColor: "rgb(77, 255, 156)",
borderColor: "rgb(77, 255, 156,0.73)",
},
],
}}
options={{
plugins: {
legend: {
display: true,
position: "right",
align: "start",
labels: {
usePointStyle: true,
},
},
},
}}
/>

How to make Chart.js with dynamic months on x-axis

I'm trying to make a Chart.js with a dynamic x-axis that will always use the next 7 months as the ticks for the x-axis.
But I'm having two problems:
The lines are not showing on my graph
The x-axis is only showing the first and last month, none of the months in-between.
Here is an example I made in paint to show what I'm trying to achieve:
And here is the code I have so far:
/* Build the charts */
var ctx = document.getElementById('ROIchart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
datasets: [{
label: 'Paid Search and Leads',
backgroundColor: 'red',
borderColor: 'red',
data: [10, 10, 10, 10, 10, 10, 10],
}, {
label: 'SEO and Content',
backgroundColor: 'green',
borderColor: 'green',
data: [0, 2, 8, 21, 57, 77, 100],
fill: true,
}]
},
// Configuration options go here
options: {
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'month'
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="ROIchart"></canvas>
With the moment.js library, you can look at the length of your array, and from a starting month generate the months, and then put them as labels
/* Build the charts */
var ctx = document.getElementById('ROIchart').getContext('2d');
var array1 = [10, 10, 10, 10, 10, 10, 10];
var months = []
for (let i = 0; i < array1.length; i++) {
months.push(moment().year(2020).month(i+1).date(0).startOf('month'))
}
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: months,
datasets: [{
label: 'Paid Search and Leads',
backgroundColor: 'red',
borderColor: 'red',
data: array1,
}, {
label: 'SEO and Content',
backgroundColor: 'green',
borderColor: 'green',
data: [0, 2, 8, 21, 57, 77, 100],
fill: true,
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'month'
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>
<canvas id="ROIchart"></canvas>

Displaying line chart for multiple months using chart.js

I have to display a line chart with two different datasets in one single chart. After execution of the query I got the plan_plan and actual_plan of the following form.
plan_plan = 0: {label: "Feb-20", plan_hrs: "20"}
1: {label: "Oct-20", plan_hrs: "94"}
actual_plan = 0: {label: "Mar-20", actual_hrs: "1"}
javacript code:
function show_Graph()
{
{
var plandata = <?php echo json_encode($plan_plan); ?>;
var actualdata = <?php echo json_encode($actual_plan); ?>;
var labels = [];
for (var i in plandata) {
labels.push(plandata[i].label);
}
for (var j in actualdata) {
labels.push(actualdata[j].label);
}
new Chart("scurve_chart", {
type: 'line',
data: {
labels: Array.from(labels),
datasets: [{
label: "Planned Hours",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
pointHoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: plandata.map(o => ({ x: Number(o.label), y: Number(o.plan_hrs)}))
},
{
label: "Actual Hours",
fill: false,
backgroundColor: "rgba(0, 255, 0, 0.75)",
borderColor: "rgba(0, 255, 0, 1)",
pointHoverBackgroundColor: "rgba(0, 255, 0, 1)",
pointHoverBorderColor: "rgba(0, 255, 0, 1)",
data: actualdata.map(o => ({x: Number(o.label), y: Number(o.actual_hrs)}))
}
]
},
options: {
tooltips: {
callbacks: {
title: (tooltipItem, data) => "Month " + data.datasets[tooltipItem[0].datasetIndex].data[tooltipItem[0].index].x
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'Hours'
}
}],
xAxes: [{
ticks: {
min: 0,
max: 53,
stepSize: 1
},
scaleLabel: {
display: true,
labelString: 'Month'
}
}]
}
}
});
}}
I want to get the month in the format (Jan-20) in x-axis and then plan_hrs and actual_hrs data in y-axis which can be shown as a line chart. And also should show a single point entry even when there are no data points to be connected. I have used the script tags:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
But it is not showing graph when I am including the following script for bootstrap:
<script src="build/js/custom.min.js">
I can help for parsing and displaying the dates on the xAxis but unfortunately I don't know Bootstrap.
Define your xAxis as follows:
xAxes: [{
type: 'time',
time: {
parser: 'MMM-YY',
unit: 'month',
displayFormats: {
month: 'MMM-YY'
}
}
}]
Chart.js internally uses Moment.js, hence you can use the following date/time formats for parsing and displaying the date. In your case, this is 'MMM-YYD'.
const plan_plan = [{label: "Feb-20", plan_hrs: "20"}, {label: "Oct-20", plan_hrs: "94"}];
const actual_plan = [{label: "Mar-20", actual_hrs: "1"}];
new Chart("scurve_chart", {
type: 'line',
data: {
datasets: [{
label: "Planned Hours",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
data: plan_plan.map(o => ({ x: o.label, y: Number(o.plan_hrs)}))
},
{
label: "Actual Hours",
fill: false,
borderColor: "rgba(0, 255, 0, 1)",
data: actual_plan.map(o => ({x: o.label, y: Number(o.actual_hrs)}))
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
type: 'time',
time: {
parser: 'MMM-YY',
unit: 'month',
displayFormats: {
month: 'MMM-YY'
}
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<canvas id="scurve_chart" height="90"></canvas>

Charts JS: Doughnut chart and hiding tooltip for specific data index within each dataset

I am trying to take a chartJS doughnut chart and instead of it displaying each piece of data on a single dataset I want each unique piece of data (with its own unique label) to display on its own dataset. This means to represent that data on each dataset it still needs two pieces of data:
- the desired value (ie. 80%)
- the difference value (ie. 20%)
After some research I figured out how to use callback function to display the dataset label to each of its data values and add a percentage character after its number value. Now I am trying to hide the tooltip for the second data value within each dataset. I am new to javascript so a little help would be appreciated! Cheers.
Chart.defaults.global.defaultFontSize = 16;
Chart.defaults.global.defaultFontColor = '#000';
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [
/* Outer doughnut data starts*/
{
data: [90, 10],
backgroundColor: [
'rgba(210, 35, 42, 1)',
'rgba(0, 0, 0, 0.05)'
],
label: 'Skill #1'
},
/* Outer doughnut data ends*/
/* Inner doughnut data starts*/
{
data: [50, 50],
backgroundColor: [
'rgba(210, 35, 42, 0.75)',
'rgba(0, 0, 0, 0.05)'
],
label: 'Skill #2'
},
/* Inner doughnut data ends*/
{
data: [15, 85],
backgroundColor: [
'rgba(210, 35, 42, 0.5)',
'rgba(0, 0, 0, 0.05)'
],
label: 'Skill #3'
},
{
data: [5, 95],
backgroundColor: [
'rgba(210, 35, 42, 0.25)',
'rgba(0, 0, 0, 0.05)'
],
label: 'Skill #4'
}
],
},
options: {
title: {
display: true,
text: 'My Skills',
fontSize: 24,
},
scales: {
xAxes: [{
gridLines: {
display: false,
drawBorder: false,
},
ticks: {
display: false,
}
}],
yAxes: [{
gridLines: {
display: false,
drawBorder: false,
},
ticks: {
display: false,
}
}]
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var dslabelamt = dataset.data[tooltipItem.index];
return data.datasets[tooltipItem.datasetIndex].label + ': ' + dslabelamt + '%';
}
}
}
}
});
https://codepen.io/manudan711/pen/aadYRj
those data-sets in chart.js don't work alike series in other charts do, but are index-based. therefore you'd require only two datasets and then you'd have to map those values accordingly; so that index position 0, 1, 2, 3, ... on both of the data arrays, would sum up to 100.

Categories