Related
I have looked at various documentation and similar questions on here, but cannot seem to find the particular solution. Apologies if I have missed anything obvious or have repeated this question!
As a bit of background info, I have implemented a graph using the Chart.js plugin and I am trying to pass the required data from a database.
The arrays of data are the following:
loggedIn: [6.3, 2.4, 7.6, 5.4, 9.9, 7.8],
available: [6.7, 2.2, 11.2, 5.5, 10.1, 7.9],
availableForExisting: [7.2, 3.1, 8.2, 5.6, 9.2, 10.2],
My problem is that only one of the line graphs is being update whilst the rest aren't. The full Chart.JS iFrame code is the following:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.bundle.min.js"></script>
</head>
<body onLoad="ready()">
<canvas id="myChart" width="250" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart");
const loggedIn = [26, 36, 42, 38, 40, 30, 12];
const available = [34, 44, 33, 24, 25, 28, 25];
const availableForExisting = [16, 13, 25, 33, 40, 33, 45];
const years = [1, 2, 3, 4, 5];
var myChart = new Chart(ctx,
{
type: 'line',
data:
{
labels: years,
datasets: [
{
label: 'Start Balance',
data: loggedIn,//[], //start empty
borderColor:
[
'rgba(164,126,44,1.000)'
],
borderWidth: 1
},
{
label: 'Interest',
data: available,//[], //start empty
borderColor:
[
'rgba(5,99,59,1.000)'
],
borderWidth: 1
},
{
label: 'End Balance',
data: availableForExisting,//[], //start empty
borderColor:
[
'rgba(255,148,112,1.000)'
],
borderWidth: 1
}
]
},
options:
{
tooltips:
{
callbacks:
{
label: function(tooltipItem, data)
{
const title = data.labels[tooltipItem.index];
const dataset = data.datasets[tooltipItem.datasetIndex];
const value = dataset.data[tooltipItem.index];
return title + ': ' + Number(value).toFixed(2) + "%";
}
},
},
onClick: handleClick
}
});
window.onmessage = function(event)
{
if (event.data && Array.isArray(event.data))
{
myChart.data.datasets[0].data = event.data[0];
myChart.data.datasets[1].data = event.data[1];
myChart.data.datasets[2].data = event.data[2];
myChart.update();
}
else
{
console.log("HTML Code Element received a generic message:");
console.log(event.data);
}
};
function handleClick(e)
{
var activeBars = myChart.getElementAtEvent(e);
var value = myChart.config.data.datasets[activeBars[0]._datasetIndex].data[activeBars[0]._index];
var label = activeBars[0]._model.label;
window.parent.postMessage(
{
"type": "click",
"label": label,
"value": value
}, "*");
}
function ready()
{
window.parent.postMessage(
{
"type": "ready"
}, "*");
}
</script>
</body>
</html>
I need to display the data in multiple line graphs, however only one is being updated. The way I am passing the data from the frontend is as follows:
let data =
{
loggedIn: [6.3, 2.4, 7.6, 5.4, 9.9, 7.8],
available: [6.7, 2.2, 11.2, 5.5, 10.1, 7.9],
availableForExisting: [7.2, 3.1, 8.2, 5.6, 9.2, 10.2],
};
$w("#html4").postMessage(data);
$w("#html4").onMessage((event) =>
{
if (event.data.type === 'ready')
{
$w("#html4").postMessage(days[year]);
}
});
I have json data in DRF which run locally at url: http://127.0.0.1:8000/api/data/ like this :
[
{
"id": 2,
"timestamp": "2020-03-15T11:46:10+07:00",
"vibration": 3,
"moisture": 70,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
},
{
"id": 6,
"timestamp": "2020-03-15T12:00:10+07:00",
"vibration": 3,
"moisture": 75,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
},
{
"id": 7,
"timestamp": "2020-03-15T13:00:10+07:00",
"vibration": 3,
"moisture": 75,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
},
{
"id": 8,
"timestamp": "2020-03-16T07:00:00+07:00",
"vibration": 3,
"moisture": 80,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
}
]
I want to make a line chart based on all the data on field "vibration" and "moisture". And i've tried it with codes like this :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Try Chart</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
<script>
function dspChrt(hum, vibrate) {
hum = loadChart().hum;
vibrate = loadChart().vibrate;
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
datasets: [{
label: 'Humidity',
data: hum, // json value received used in method
backgroundColor: "rgba(153,255,51,0.4)"
}, {
label: 'Vibration',
data: vibrate,
backgroundColor: "rgba(255,153,0,0.4)"
}]
}
});
}
</script>
<script>
var myVar = setInterval(loadChart, 60000); // updates chart every one minute
function loadChart()
{
var data, hum, vibrate;
var requestURL = 'http://127.0.0.1:8000/api/data'; //URL of the JSON data
var request = new XMLHttpRequest({mozSystem: true}); // create http request
request.onreadystatechange = function() {
if(request.readyState == 4 && request.status == 200) {
data = JSON.parse(request.responseText);
for (var i=0; i<data.length;i++) {
hum = data[i].moisture;
vibrate = data[i].vibration;
}
console.log('hum', hum);
console.log('vibrate', vibrate);
console.log('data', data);
return data,hum,vibrate;
dspChrt(hum, vibrate);
}
}
request.open('GET', requestURL);
request.send(); // send the request
}
</script>
</head>
<body onload="loadChart()">
<div class="container">
<h2>Try Chart</h2>
<div>
<canvas id="myChart"></canvas>
</div>
</div>
</body>
</html>
But it doesn't work, the data doesn't appear on the chart and in the inspect element of the web page only return the last data of "vibration" and "moisture". I want all the data in "vibration" and "moisture" to be plotted on the chart, not only the last one.
this is the inspect element of the webpage :
inspect-element-chart
I think this is happen because format of the json. Anybody know how to fix it? I am still a newbie in programming. Thank you before
I've tried to set up a sandbox example without using the request and having the JSON as a JS Object in the JS code.
const JSONdata = [
{
"id": 2,
"timestamp": "2020-03-15T11:46:10+07:00",
"vibration": 3,
"moisture": 70,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
},
{
"id": 6,
"timestamp": "2020-03-15T12:00:10+07:00",
"vibration": 3,
"moisture": 75,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
},
{
"id": 7,
"timestamp": "2020-03-15T13:00:10+07:00",
"vibration": 3,
"moisture": 75,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
},
{
"id": 8,
"timestamp": "2020-03-16T07:00:00+07:00",
"vibration": 3,
"moisture": 80,
"gps_latitude": "-7.7713794",
"gps_longitude": "110.3753111",
"gyro_x": 6.58,
"gyro_y": 85.0,
"gyro_z": -3.9,
"accelero_x": 6.58,
"accelero_y": 85.0,
"accelero_z": -3.9,
"displacement": 10,
"node_id": 1
}
]
function dspChrt(hum, vibrate) {
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
datasets: [{
label: 'Humidity',
data: hum, // json value received used in method
backgroundColor: "rgba(153,255,51,0.4)"
}, {
label: 'Vibration',
data: vibrate,
backgroundColor: "rgba(255,153,0,0.4)"
}]
}
});
}
// Not sure how this is expected to work? Is the Data a Stream?
//var myVar = setInterval(loadChart, 60000); // updates chart every one minute
function loadChart(){
var data, hum = [], vibrate = [];
/*doing it with the JSON already in the JS for this example:
var requestURL = 'http://127.0.0.1:8000/api/data'; //URL of the JSON data
var request = new XMLHttpRequest({mozSystem: true}); // create http request
request.onreadystatechange = function() {
if(request.readyState == 4 && request.status == 200) {
data = JSON.parse(request.responseText);
*/
data = JSONdata;
for (var i=0; i<data.length;i++) {
hum.push(data[i].moisture);
vibrate.push(data[i].vibration);
}
/*
console.log('hum', hum);
console.log('vibrate', vibrate);
console.log('data', data);
*/
dspChrt(hum, vibrate);
/*doing it with the JSON already in the JS for this example:
}
}
request.open('GET', requestURL);
request.send(); // send the request
*/
}
loadChart();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Try Chart</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
</head>
<body onload="loadChart()">
<div class="container">
<h2>Try Chart</h2>
<div>
<canvas id="myChart"></canvas>
</div>
</div>
</body>
</html>
The most important thing is to set up your hum and vibrate variables as empty arrays:
function loadChart(){
var data, hum = [], vibrate = [];
...
}
And then to push onto them each item's moisture and vibration property (each item is each object in your JSON array):
for (var i=0; i<data.length;i++) {
hum.push(data[i].moisture);
vibrate.push(data[i].vibration);
}
By this at the end of the for-loop the variables are:
hum = [70, 75, 75, 80]
vibrate = [3, 3, 3, 3]
Also, you had your functions calling each other but neither of the functions being invoked.
So you should have this function with arguments:
function dspChrt(hum, vibrate) {
var ctx = document.getElementById('myChart').getContext('2d');
...
}
And don't need to then call the other function loadChart again from this as the values are already passed in - we already have them
function loadChart(){
var data, hum = [], vibrate = [];
...
/*
console.log('hum', hum);
console.log('vibrate', vibrate);
console.log('data', data);
*/
dspChrt(hum, vibrate);
...
}
And notice this function doesn't need to return anything, we just need to call dspChart(hum, vibrate)
And finally, we need to invoke/call our loadChart() function to make this happen and the Chart to be created.
loadChart();
Finally, the output is this (click Show code snippet and then run it):
And so finally, the code with the XMLHttpRequest happening is the following, but it obviously won't work on Stack Overflow:
function dspChrt(hum, vibrate) {
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
datasets: [{
label: 'Humidity',
data: hum, // json value received used in method
backgroundColor: "rgba(153,255,51,0.4)"
}, {
label: 'Vibration',
data: vibrate,
backgroundColor: "rgba(255,153,0,0.4)"
}]
}
});
}
function loadChart(){
var data, hum = [], vibrate = [];
var requestURL = 'http://127.0.0.1:8000/api/data'; //URL of the JSON data
var request = new XMLHttpRequest({mozSystem: true}); // create http request
request.onreadystatechange = function() {
if(request.readyState == 4 && request.status == 200) {
data = JSON.parse(request.responseText);
//data = JSONdata;
for (var i=0; i<data.length;i++) {
hum.push(data[i].moisture);
vibrate.push(data[i].vibration);
}
/*
console.log('hum', hum);
console.log('vibrate', vibrate);
console.log('data', data);
*/
dspChrt(hum, vibrate);
}
}
request.open('GET', requestURL);
request.send(); // send the request
}
loadChart();
//var myVar = setInterval(loadChart, 60000); // updates chart every one minute
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Try Chart</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
</head>
<body onload="loadChart()">
<div class="container">
<h2>Try Chart</h2>
<div>
<canvas id="myChart"></canvas>
</div>
</div>
</body>
</html>
I am trying to plot chart using canvas.js!
As I want the data dynamically from my API, I created an array and is then passing it into the json object.
so I did the following:
<!DOCTYPE HTML>
<html>
<head>
<script>
var xhr = new XMLHttpRequest(),
method = "GET",
url = "url";
xhr.open(method, url, true);
var data_array = [];
xhr.send();
window.onload = function () {
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var api_data = xhr.responseText;
var api_json = JSON.parse(api_data);
var data = api_json["data"];
for(var i=0; i<data.length; i++) {
dp_data = data[i];
dp_median = dp_data["dp_median_price"];
dp_date = dp_data["date"];
var datearray = dp_date.split("-");
var newdate = datearray[0] + ', ' + datearray[1] + ', ' + datearray[2];
data_array.push({x:newdate, y:Number(dp_median)});
}
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "title"
},
axisX: {
valueFormatString: "YYYY MM DD"
},
axisY2: {
title: "Median Price",
prefix: "₹",
suffix: ""
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "top",
horizontalAlign: "center",
dockInsidePlotArea: true,
itemclick: toogleDataSeries
},
data:[
{
type:"line",
axisYType: "secondary",
name: "name1",
showInLegend: true,
markerSize: 1,
yValueFormatString: "₹#,###",
dataPoints: [
{ x: new Date(2015, 08, 01), y: 648 },
{ x: new Date(2015, 09, 01), y: 649 },
{ x: new Date(2015, 10, 01), y: 649 },
{ x: new Date(2017, 03, 01), y: 400 },
{ x: new Date(2017, 04, 01), y: 749 },
{ x: new Date(2017, 05, 01), y: 740 }]
},
{
type:"line",
axisYType: "secondary",
name: "name2",
showInLegend: true,
markerSize: 1,
yValueFormatString: "₹#,###",
dataPoints: data_array
}
]
});
chart.render();
function toogleDataSeries(e){
if (typeof(e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else{
e.dataSeries.visible = true;
}
chart.render();
}
}
}
};
</script>
</head>
<body>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
Here, I cant read the data_array. How do I pass it in the chart data?
Above way is not working!
But when I pass data in a static way it works!
My array is in exact format as shown example of static information!
output of console.log(data_array) =
0:
x: "2019, 08, 29"
y: 1935
__proto__: Object
The problem is in how you try to track your ajax request.
The onredystatechange event fires multiple times during the executon of the xhr request.
0 - UNSENT Client has been created. open() not called yet.
1 - OPENED open() has been called.
2 - HEADERS_RECEIVED send() has been called, and headers and status are available.
3 - LOADING Downloading responseText holds partial data.
4 - DONE The operation is complete.
It is only when the state is 4 that you should start processing your data.
xhr.onreadystatechange = function () {
if (xhr.readyState ==0 4 and xhr.status === 200) {
//Process your data
I made a chart that shows machines and the times that was taken for them to be fixed (machines X, time Y)
the data is loaded dynamically via mysql like the following
<?php
include_once(“connexion.php”);
ini_set(‘max_execution_time’,300);
//ini_set(‘error_reporting’, E_ALL);
$sq = “select machine,date_tech,time(time_fin – time_deb) as diff from action_archiv_tech WHERE (date_tech BETWEEN ‘2018-09-10’ AND ‘2018-10-06’)”;
$r = mysql_query($sq) or (die(mysql_error()));
while($tab = mysql_fetch_assoc($r)) {
$machine = $tab[‘machine’];
$diff = $tab[‘diff’];
// $data[] = [“label”=>$machine, “y”=>$diff];
$data[] = array(
‘label’ => $tab[‘machine’],
‘y’ => $tab[‘diff’]
);
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset=”UTF-8”>
<script>
window.onload = function () {
var chart = new CanvasJS.Chart(“chartContainer”, {
theme:”light2″,
animationEnabled: true,
title:{
text: “PM”
},
axisY :{
includeZero: false,
title: “Heures”,
suffix: “H”
},
toolTip: {
shared: “true”
},
legend:{
cursor:”pointer”,
itemclick : toggleDataSeries
},
data: [
{
type: “spline”,
showInLegend: true,
yValueFormatString: “##.00H”,
name: “Curative”,
dataPoints: <?php echo json_encode($data); ?>
}
]
});
chart.render();
function toggleDataSeries(e) {
if (typeof(e.dataSeries.visible) === “undefined” || e.dataSeries.visible ){
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
chart.render();
}
}
</script>
</head>
<body>
<div id=”chartContainer” style=”height: 370px; max-width: 1920px; margin: 0px auto;”></div>
<script src=”../../canvasjs.min.js”></script>
</body>
</html>
However the results are not like the expected
results : https://i.stack.imgur.com/zyIZM.png
Could you please help me figure out how to solve this problem :)
It seems like you are passing date-time in y-values, whereas CanvasJS supports only numeric in axisY. Please refer documentation for more info. However you can workaround this by passing -values as timestamp and format the value in axis-labels and toolTip as shown in below example, here is the JSFiddle for the same.
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Machine Operating Time"
},
axisY: {
minimum: (new Date(2016, 0, 25, 17, 30)).getTime(),
interval: (12 * 60 * 60 * 1000),
labelFormatter: function(e){
return CanvasJS.formatDate(e.value, "DD-MMM h:mm TT");
}
},
toolTip:{
contentFormatter: function ( e ) {
return "<strong>Machine " + e.entries[0].dataPoint.label + "</strong></br> Start Time: " + CanvasJS.formatDate(e.entries[0].dataPoint.y[0], "DD-MMM h:mm TT") + "</br> Stop Time: " + CanvasJS.formatDate(e.entries[0].dataPoint.y[1], "DD-MMM h:mm TT");
}},
data: [{
type: "rangeColumn",
dataPoints: [
{ label: "A", y: [(new Date(2016, 0, 25, 18, 30)).getTime(), (new Date(2016, 0, 26, 11, 00)).getTime()] }, //.getTime() returns timestamp => y-value is numeric
{ label: "B", y: [(new Date(2016, 0, 26, 12, 00)).getTime(), (new Date(2016, 0, 27, 14, 00)).getTime()] },
{ label: "C", y: [(new Date(2016, 0, 27, 3, 30)).getTime(), (new Date(2016, 0, 27, 14, 00)).getTime()] },
{ label: "D", y: [(new Date(2016, 0, 27, 12, 00)).getTime(), (new Date(2016, 0, 28, 14, 00)).getTime()] }
]
}]
});
chart.render();
<script src="http://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 260px; width: 100%;"></div>
as indicated by red arrow. why it is showing -25 line in chart
javascript which i am using is.
<!DOCTYPE html>
<html>
<head> <meta http-equiv="refresh" content="30" />
<title>Analytics of Payment Service</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {
packages: ["corechart", "bar"]
});
google.setOnLoadCallback(function(){
drawChart2()
})
function drawChart2() {
var listOfDataCC =$!{dataForCCInvoice}
var outputArrayForInvoiceAndCredit = new Array();
// header
var headerArray1 = ['Day', 'cc', 'In'];
outputArrayForInvoiceAndCredit.push(headerArray1);
for (var i = 0; i < listOfDataCC.length; i++){
var obj1 = listOfDataCC[i];
var innerArray = new Array();
innerArray[0] = obj1.date;
innerArray[1] = obj1.CCount;
innerArray[2] = obj1.inCount;
outputArrayForInvoiceAndCredit.push(innerArray);
}
var data2 = google.visualization.arrayToDataTable(outputArrayForInvoiceAndCredit);
var options2 = {
title: 'CC/In Details',
curveType: 'function',
legend: {
position: 'bottom'
}
};
var chart2 = new google.visualization.LineChart(document.getElementById('cc/in'));
chart2.draw(data2, options2);
}
</script>
</head>
<body>
<div id="cc/in" style="width: 900px; height: 500px"></div>
</body>
</html>
value of $!{dataForCCInvoice} is values in json format.
json values are.
[
{
"date": "15-APR-16",
"CCount": 38,
"inCount": 18
},
{
"date": "16-APR-16",
"CCount": 9,
"inCount": 14
},
{
"date": "17-APR-16",
"CCount": 9,
"inCount": 3
},
{
"date": "18-APR-16",
"CCount": 52,
"inCount": 44
},
{
"date": "19-APR-16",
"CCount": 59,
"inCount": 44
},
{
"date": "20-APR-16",
"CCount": 9,
"inCount": 7
}
]
what i am missing here. sometimes its working fine but dont know why that -25 line is appearing
To solve this, you can add the following to your options :
vAxis: {viewWindow: {min: 0}}
So it will look like this :
var options2 = {
title: 'CC/In Details',
curveType: 'function',
legend: {
position: 'bottom'
},
vAxis: {
viewWindow: {
min: 0
}
}
};
I'm not sure why it show the -25 line in the first place though. I think it's due to the value of 3 in inCount, which is low enough to make the charts display negative values.