Parse an object to chart.js instead of arrays? - javascript

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.

Related

Update Chart JS data dynamically and add new data, remove old data to create timeline "like" chart

I'm building a realtime Chart JS chart which is meant to show data and update every few seconds, I attach my chart JS code below, which randomises data on page load, I have a labels array which I need to change to whatever the current date/time is, and after every X number of items it removes the previous so that the graph is essentially a timeline showing real time stats, I'm first trying to figure out how to get my chart to update data every few seconds and aren't sure how to do this:
$(document).ready(function(){
// Random data on page load
var datasetValue = [];
var count = 70;
for (var j = 0; j < count; j++) {
datasetValue[j] = {
data: [
Math.round(Math.random() * 100),
Math.round(Math.random() * 100)-10,
Math.round(Math.random() * 100),
Math.round(Math.random() * 100)-10,
Math.round(Math.random() * 100),
Math.round(Math.random() * 100)-10,
Math.round(Math.random() * 100)
]
}
}
var mydata = {
datasets: datasetValue
}
// Our chart
var ctx = document.getElementById('status-chart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "Max",
fill: false,
borderColor: '#f44336',
data: mydata.datasets[1].data,
}, {
label: "Free",
fill: false,
borderColor: '#4CAF50',
data: mydata.datasets[3].data,
}, {
label: "Total",
fill: false,
borderColor: '#607D8B',
data: mydata.datasets[2].data,
}, {
label: "Used",
fill: false,
borderColor: '#2196F3',
data: mydata.datasets[4].data,
}]
},
options: {
legend: {
display: true,
labels: {
fontColor: '#000'
}
}
}
});
});
you can use chart.update() method with assigning a new dataset
<canvas id="myChart" width="400" height="250"></canvas>
<input type="button" value="New Data" onclick="RandomData()">
var canvas = document.getElementById('myChart');
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My 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: 5,
pointHitRadius: 10,
data: [65, 59, 80, 0, 56, 55, 40],
}
]
};
function RandomData(){
var newData=[];
for(var i=0;i<7;i++){
newData.push(Math.round(Math.random() * 100))
}
myLineChart.data.datasets[0].data =newData;
myLineChart.update();
}
var option = {
showLines: true
};
var myLineChart = Chart.Line(canvas,{
data:data,
options:option
});
please see a demo here

Animate datasets separately

I'm trying to display two datasets in a line graph but animating the second dataset some seconds after the first one.
I'm using the CHART.JS version 2.6.0 and I saw a lot of samples using previous versions (1.xx), but all of them does not function in this new version cause API had changed.
I tried the documentation (see here) but it is really very poor to newbies, since the ANIMATION event doc has only a single basic sample.
WHat I want to do is basically this:
var ctx = document.getElementById("myChart").getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
data: [65, 0, 80, 81, 56, 85, 40]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
data: [0, 0, 0, 0, 0, 0, 0]
}
]
};
var data2 = [28, 48, 40, 19, 86, 27, 90];
var done = false;
var myLineChart = new Chart(ctx).Line(data, {
animationEasing: 'linear',
onAnimationComplete: function () {
if (!done) {
myLineChart.datasets[1].points.forEach(function (point, i) {
point.value = data2[i];
});
myLineChart.update();
done = true;
}
}
});
You can see this code functioning here, but this sample does not function in version 2.6, even if adapting it to the new syntax.
So, can you help me to achieve the same effect using the Chart.JS 2.6?
Thanks in advance!
SOLUTION for ChartJS v2.6
var done = false;
var data2 = [28, 48, 40, 19, 86, 27, 90];
var ctx = document.getElementById("myChart").getContext("2d");
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
backgroundColor: "rgba(220,220,220,0.2)",
borderColor: "rgba(220,220,220,1)",
pointBackgroundColor: "rgba(220,220,220,1)",
pointBorderColor: "#fff",
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(220,220,220,1)",
data: [65, 0, 80, 81, 56, 85, 40]
}, {
label: "My Second dataset",
backgroundColor: "rgba(151,187,205,0.2)",
borderColor: "rgba(151,187,205,1)",
pointBackgroundColor: "rgba(151,187,205,1)",
pointBorderColor: "#fff",
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(151,187,205,1)",
data: [0, 0, 0, 0, 0, 0, 0]
}]
},
options: {
animation: {
easing: 'linear',
onComplete: function(e, i) {
if (!done) {
this.data.datasets[1].data = data2;
/* we need to update chart within setTimeout,
as there seems to be an issue when updating the chart
at first animation onComplete function call */
setTimeout(function() {
this.update();
}.bind(this), 100);
done = true;
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="myChart" height="300" width="800"></canvas>

How to hide tooltips with their respective dataset

I'm using charts.js. For my current need, I managed to find a way to configure tooltips to be always visible regardless of the hover event. My problem is that the tooltip visibility does not follow the dataset behaviour. On charts.js, you can click on a dataset in order to remove it from the graph. My graph does that, but the tooltips are still there visible, floating within the graph with no dataset to represent. Is there a way to hide then with the dataset data when the label is clicked ?
Here is an example of the current state of what i said. https://jsfiddle.net/CaioSantAnna/ddejheg0/ .
HTML
<canvas id="linha"></canvas>
Javascript
Chart.plugins.register({
beforeRender: function (chart) {
if (chart.config.options.showAllTooltips) {
// create an array of tooltips
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function (dataset, i) {
chart.getDatasetMeta(i).data.forEach(function (sector, j) {
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector]
}, chart));
});
});
// turn off normal tooltips
chart.options.tooltips.enabled = false;
}
},
afterDraw: function (chart, easing) {
if (chart.config.options.showAllTooltips) {
// we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
if (!chart.allTooltipsOnce) {
if (easing !== 1)
return;
chart.allTooltipsOnce = true;
}
// turn on tooltips
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
tooltip.initialize();
tooltip.update();
// we don't actually need this since we are not animating tooltips
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
});
ctx = document.getElementById("linha");
var linha = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: true,
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,
responsive: true,
animation: true,
},
{
label: "Second dataset",
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(0,0,0,0.4)",
borderColor: "rgba(0,0,0,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(0,0,0,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(0,0,0,1)",
pointHoverBorderColor: "rgba(0,0,0,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [13, 78, 60, 75, 90, 10, 27],
spanGaps: false,
responsive: true,
animation: true,
}
]
},
options: {
tooltips: {
callbacks: {
title: function (tooltipItem, data) { return "" },
label: function (tooltipItem, data) {
var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || 'Other';
var label = data.labels[tooltipItem.index];
return value;
}
}
},showAllTooltips: true
}
});
To reproduce the problem, just click in one of the labels on the top of the graph.
Thanks in advance.
Just to close the question, I ended up changing to amcharts(https://www.amcharts.com/). It has features like the one i was trying to achieve with chart.js and is free to use under a linkware license.
Thanks again.

How to create a linechart with Chart.JS (not filled)

I am trying to create a line chart with chart.js library, my goal is that the chart should be a single line, the area under it MUST NOT BE FILLED.
But whatever color I put, I dont see that its getting refreshed.
this is the JS that generates the chart.
<table style="width: 100%">
<tr>
<td style="width: 50%; text-align: center">
<canvas id="canvasForLineChart" height="200" width="400">Chart is Loading...</canvas>
</td>
</tr>
</table>
<script type="text/javascript">
////////////////////////////////////////////////////////////////////////////////////////////////////////
//Line Chart JSON Config (Line Chart Has fixed 1 data series here)
var lineChartData = {
//labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
fill: false,
lineTension: 0.1,
//backgroundColor: "#000000",
//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: [0]
}
]
}
//LineChart Update method
function UpdateLineChart(data) {
//Set data returned from Server
//lineChartData.datasets[0].fillColor = data.colorString;
lineChartData.datasets[0].data = data.lineChartData;
lineChartData.labels = data.hora;
//Update the Pie Chart
var canvasForLineChart = document.getElementById("canvasForLineChart");
var context2DLine = canvasForLineChart.getContext("2d");
new Chart(context2DLine).Line(lineChartData);
}
</script>
But my result is this:
And I want something like this:
According to the Chart JS Docs, you'll want to specify:
fill: false
in your chart options. Your code would look something like this:
function UpdateLineChart(data) {
//Set data returned from Server
lineChartData.datasets[0].data = data.lineChartData;
lineChartData.labels = data.hora;
//Update the Pie Chart
var canvasForLineChart = document.getElementById("canvasForLineChart");
var context2DLine = canvasForLineChart.getContext("2d");
var myChart = new Chart(context2DLine, {
data: {
datasets: [{
fill: false,
lineTension: 0.1,
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [0]
}]
}
});
}
backgroundColor 'rgba(0,0,0,0.1)'
That should set your opacity to .1, you can go to zero I think but you should test it. I see you commented out the border color you had set to 1 opacity which is solid.
fill: false
should do the work, where do you call the UpdateLineChart function?

Chart.js Line-Chart with different Labels for each Dataset

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
}
}],
}
}
});

Categories