Using Chart.js you can create line charts and for that you have to privde labels and datasets. for example:
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
}
]
};
The Problem here is that you have a fix amount of labels (7 in this case) and you also need to provide 7 data entries for each dataset. Now what if you have an unknown amount of labels and data entries?
What if one data entry contains a number and a time:
Entry {
number: 127
time: 10:00
}
What if you want to show all times on the X-Axis and all Numbers on the Y-Axis sorted by the time on the X-Axis. Is that possible with Chart.js?
I had a battle with this today too.
You need to get a bit more specific with your dataset. In a line chart "datasets" is an array with each element of the array representing a line on your chart. Chart.js is actually really flexible here once you work it out. You can tie a line (a dataset element) to an x-axis and/or a y-axis, each of which you can specify in detail.
In your case if we stick with a single line on the chart and you want the "time" part of the entry to be along the bottom (the x-axis) then all your times could go into the "labels" array and your "number" would be pin-pointed on the y-axis. To keep it simple without specifying our own scales with x and y axes and given this data:
var MyData = [{time:"10:00", number: "127"},
{time:"11:00", number: "140"},
{time:"12:00", number: "135"},
{time:"13:00", number: "122"}];
You could set up the "data" property of your chart to be:
var data = {
labels: ["10:00", "11:00", "12:00", "13:00"],
datasets: [
{
label: "My First dataset",
// Insert styling, colors etc here
data: [{x: "10:00", y: 127},
{x: "11:00", y: 140},
{x: "12:00", y: 135},
{x: "13:00", y: 122}]
}
]};
Note that the data array is now a bit more specific with each element of data plotting itself on the x-axis by referencing one of the labels rather than just being a raw number. You can now put another dataset object in the datasets array following this pattern and have two lines, obviously give your lines different colours and names ("label").
Hope this helps.
I found a really good solution here: https://github.com/chartjs/Chart.js/issues/3953
Basically, you can add in your own 'labels' property to each dataset and leverage it in the callbacks for the xAxes labels, tooltips, or whatever you like.
var ctx = $("#myChart");
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [{
data: [1, 2, 3, 4, 5],
backgroundColor: [
'green',
'yellow',
'red',
'purple',
'blue',
],
labels: [
'green',
'yellow',
'red',
'purple',
'blue',
]
}, {
data: [6, 7, 8],
backgroundColor: [
'black',
'grey',
'lightgrey'
],
labels: [
'black',
'grey',
'lightgrey'
],
},]
},
options: {
responsive: true,
legend: {
display: false,
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ': ' + dataset.data[index];
}
}
}
}
});
What's important here is this piece:
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
var index = tooltipItem.index;
return dataset.labels[index] + ': ' + dataset.data[index];
}
}
}
Since there's a number of questions in your post, I'll try to help out with at least some of them. In the case of your Entry model with a number and a time you should create a scattered graph. Here you define data objects with x and y values as shown in my example below. It requires that each entry x has a corresponding y.
Have a look at the scatter chart.
http://www.chartjs.org/docs/#line-chart-scatter-line-charts
var d = new Date();
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Scatter Dataset',
data: [{
x: new Date().setDate(d.getDate()-5),
y: 0
}, {
x: new Date(),
y: 10
}, {
x: new Date().setDate(d.getDate()5),
y: 5
}]
}]
},
options: {
scales: {
xAxes: [{
type: "time",
time: {
format: "HH:mm",
unit: 'hour',
unitStepSize: 2,
displayFormats: {
'minute': 'HH:mm',
'hour': 'HH:mm'
},
tooltipFormat: 'HH:mm'
},
gridLines: {
display: false
}
}],
}
}
});
Related
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>
I've made two charts, one line chart and one bar-chart, that you can switch between and the charts contains different data. The problem is that I can't seem to make them begin at zero? Where in the script do I put the code so both charts begin at zero, because now it just doesn't work or the whole bar just disappears.
<script>
let lineConfig = {
type: 'line',
data: {
labels: ["2012", "2013", "2014", "2015", "2016", "2017"],
datasets: [{
label: "Miljoner ton",
data: [56.38, 59.3, 61.81, 58.83, 52.32, 66.86],
lineTension: 0.1,
backgroundColor: "rgba(0,255,0,0.4)",
borderColor: "green", // The main line color
borderCapStyle: 'square',
pointBorderColor: "white",
pointBackgroundColor: "green",
pointBorderWidth: 1,
pointHoverRadius: 8,
pointHoverBackgroundColor: "yellow",
pointHoverBorderColor: "green",
pointHoverBorderWidth: 2,
pointRadius: 4,
}]
}
},
barConfig = {
type: 'bar',
data: {
labels: ['Palmolja', "Sojaolja", 'Animaliskt fett', 'Solrosolja', 'Rapsolja', 'Annat'],
datasets: [{
label: "Procent",
data: [28.6, 25.3, 13.2, 8.0, 12.2, 9.6],
backgroundColor: "rgba(0,255,0,0.4)",
borderColor: "green", // The main line color
borderCapStyle: 'square',
pointBorderColor: "white",
pointBackgroundColor: "green",
pointBorderWidth: 1,
pointHoverRadius: 8,
pointHoverBackgroundColor: "yellow",
pointHoverBorderColor: "green",
pointHoverBorderWidth: 2,
pointRadius: 4,
}]
}
},
activeType = 'bar', // we'll start with a bar chart.
myChart;
function init(config) {
// create a new chart with the supplied config.
myChart = new Chart(document.getElementById('chart'), config);
}
// first init as a bar chart.
init(barConfig);
document.getElementById('switch').addEventListener('click', function(e) {
// every time the button is clicked we destroy the existing chart.
myChart.destroy();
if (activeType == 'bar') {
// chart was a bar, init a new line chart.
activeType = 'line';
init(lineConfig);
return;
}
// chart was a line, init a new bar chart.
activeType = 'bar';
init(barConfig);
});
</script>
Assuming you mean for your linear y-axis then the documentation specifies the following:
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
Edit as per OP comment:
The options property is a sibling of type and data, e.g.:
{
type: 'line',
data: {
labels: [...],
datasets: [{
data: [...]
}]
},
options: {
...
}
}
I want to draw a chart with opposite bars like this (please ignore the yellow part):
This is my attempt using Chart.js:
You can see that there are 2 things need to be fixed:
The blue and red bar should be stacked
Both ends of the y-axis should show positive numbers
How can I achieve those ?
You can use the stacking and custom ticks feature to produce the result you want.
Sample JS Fiddle
var ctx = document.getElementById('wrapper').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'bar',
// The data for our dataset
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45],
stack: 'a'
}, {
label: "My Second dataset",
backgroundColor: 'rgb(2, 99, 132)',
borderColor: 'rgb(2, 99, 132)',
data: [-10, -110, -15, -12, -120, -130, -145],
stack: 'b'
}]
},
// Configuration options go here
options: {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true,
ticks: {
callback: function (value, index, values) {
return value < 0 ? -value : value;
}
}
}]
}
}
});
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>
I am trying to parse an object to chart.js instead of using an array. This is my object:
var obj = {
"and":2,
"two":1,
"too":1,
"mother":2
}
I would like to parse my obj into chart.js, so it creates a chart from that object's data. For instance, if we take a bar chart, it would put and first with 2 up the Y-axis. Followed by two with 1 up the Y-axis and so on.
How to create the bar chart:
var ctx = document.getElementById("myChart");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
}
]
};
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data
});
This has been taken directly from their website. All I need is to change out the data.labels with the key from my object and the data.datasets[0].data with the values. Doing this is relatively easy, as I can just reverse my object into arrays, but the real question is: is it possible to parse an object as the chart's data instead of arrays?. Thanks!
Unlike what you said in your comment, it is actually possible to do what you want.
You just need to use chart.js plugins, which allow you to handle your chart before or after specific events (such as the update, the rendering, etc.) and they are also easy to instance :
Chart.pluginService.register({
beforeInit: function(chart) {
// This will be triggered before the chart is created
}
});
Instead of creating your chart with default data and labels you don't want, just add empty arrays like this :
var data = {
labels: [],
datasets: [{
label: "My dataset",
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
data: []
}]
};
And then in your beforeInit event, you just have to populate those arrays using your object :
beforeInit: function(chart) {
// This is where your chart data is stored
var data = chart.config.data;
// For each item in your object
for (var key in obj) {
// This is for security - check `http://stackoverflow.com/a/684692/4864023`
if (obj.hasOwnProperty(key)) {
// Add the key as a new xAxe label ...
data.labels.push(key);
// ... and the value as a new data
data.datasets[0].data.push(obj[key]);
}
}
}
See this jsFiddle for the final result.