How to make chartjs chart with time y-axis? - javascript

I have data something like this:
{
"measurements": [
{
"id": 10,
"key": "Demoo",
"value": "00:00:03.733;",
"date": "2023-02-08",
"time": "11:05",
"value_time_formatted": "00:00:03.733"
},
{
"id": 11,
"key": "Demooo 2",
"value": "00:00:05.191;",
"date": "2023-02-08",
"time": "11:31",
"value_time_formatted": "00:00:05.191"
},
{
"id": 12,
"key": "Demo 22",
"value": "00:00:03.002;",
"date": "2023-02-08",
"time": "11:31",
"value_time_formatted": "00:00:03.002"
}
]}
And when I try out to make a line chart from the date as labels and value_time_formatted as values I get this error:
ERROR TypeError: Cannot create property 'data' on string '00:00:03.733'
The code for bind chart values looks like this:
this.lineBarLabels = [];
this.lineBarValue = [];
res.measurements.forEach(element => {
this.lineBarLabels.push(element.date);
this.lineBarValue.push(element.value_time_formatted);
});
this.lineBar = new Chart(this.linePresents.nativeElement, {
type: 'line',
data: {
labels: this.lineBarLabels,
datasets: this.lineBarValue
}
});
this.lineBar.update();
I tried to convert that time into milliseconds but looks so ugly on-screen and the user needs to convert it back to hours, minutes, seconds, and milliseconds which is so bad from customer side :(

Your code has a few issues, here the two I could spot:
the Main error ocurres because chartjs expects a object array for the property dataset, so in your case you would have to change your code to something like this:
this.lineBar = new Chart(this.linePresents.nativeElement, {
type: 'line',
data: {
labels: this.lineBarLabels,
datasets: [{data: this.lineBarValue}]
}
});
The array this.lineBarLabels is never set (will be a empty array), you would have to change: this.lineBarLabels.includes(element.date); to this.lineBarLabels.push(element.date);
These are the main issues, I don't understand what output should you are looking for, and I don't think that setting the values to strings value_time_formatted will work, but if you fix the above mentioned points, you will be a step closer to a working chart.
Update:
It seems you fixed on mistake in your question, if you want to improve your code here is a tip for you time convertion (link to relevant documentation):
const date = new Date();
// A cleaner solution
let aShortWay = date.toISOString().substring(11,23);
// Your Sode: Not really readable, and pretty long
let yourCode = (date.getUTCHours() ? (date.getUTCHours() > 9 ? date.getUTCHours() : '0' + date.getUTCHours()) : '00') + ':' +
(date.getUTCMinutes() ? (date.getUTCMinutes() > 9 ? date.getUTCMinutes() : '0' + date.getUTCMinutes()) : '00') + ':' +
(date.getUTCSeconds() ? (date.getUTCSeconds() > 9 ? date.getUTCSeconds() : '0' + date.getUTCSeconds()) : '00') + '.' +
(date.getUTCMilliseconds() > 99 ? date.getUTCMilliseconds() : date.getUTCMilliseconds() > 9 ? '0' + date.getUTCMilliseconds() : '00' + date.getUTCMilliseconds());
console.info(`aShortWay Time:${aShortWay}`)
console.info(`yourCode Time:${yourCode}`)

I finally find a solution, hope that someone will use it in the right way :)
After this part of the code:
res.measurements.forEach(element => { this.lineBarLabels.push(element.date); this.lineBarValue.push(element.value_time_formatted); }); this.createLineChart();
I made this createLineChart() method to parse and render the chart:
public createLineChart() {
this.lineBar = new Chart(this.linePresents.nativeElement, {
type: 'line',
data: {
labels: this.lineBarLabels,
datasets: [{label: this.translate.instant('time'), data: this.lineBarValue, fill: false}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
ticks: {
callback: function (value) {
const date = new Date(Number(value) * 1000);
return date.toISOString().substring(11,23);
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
const date = new Date(Number(context.formattedValue) * 1000);
return date.toISOString().substring(11,23);
}
}
}
}
}
}
);
this.lineBar.update();
}

Related

dynamically adding series to highcharts

I'm relative new to highcharts so I'm not that knowledgeable.
But what I am trying to do is that I am trying to dynamically create series with a name and some x, y values. To get the x and y values I use two dictionaries looking like this:
The X values. They are dates
The Y values. They are seconds
What I want to do is create a series that have the names of the keys and then they can have multiple points for x, y values.
So for example at "Fiber_Mätning" I have two values in the key in both dictionaries. What I want to do is that I create a series with the name "Fiber_Mätning", and then it should have two points where I give both x and y value.
So the 1st point in "Fiber_Mätning" would be x:"2020-10-28" y:"28800"
and the 2nd point in "Fiber_Mätning" would be x:"2020-10-29" y:"18000"
After that I would move on onto the next key in both dictionaries and do the same. So the way I create the series need to be a function that is dynamically creating series and the points depending on the amount of keys and values in the dictionaries.
Currently my highchart code looks like this:
$('#container').highcharts({
chart:{
type: 'column',
events:{
load: function(){
RedrawColumns(this)
},
redraw: function(){
RedrawColumns(this)
}
}
},
title:{
text: 'Time worked by {{user_to_show}}'
},
subtitle:{
text:'{{user_to_show}}´s flex time: '
},
tooltip:{
formatter: function (){
var text = 'Date: ' + this.x + '<br>' + 'Time: ' + secondsTimeSpanToHMS(this.y/1000) +
'<br>' +'Extra info:' + {{extra_info|safe}}[this.x];
return text;
}
},
xAxis:
{
categories: {{all_dates|safe}}
},
yAxis:
[{
title:
{
text: '' //If it isnt given '' it will display "value" so using '' to hide it
},
gridLineWidth: 1,
type: 'datetime', //y-axis will be in milliseconds
dateTimeLabelFormats:
{ //force all formats to be hour:minute:second
second: '%H:%M:%S',
minute: '%H:%M:%S',
hour: '%H:%M:%S',
day: '%H:%M:%S',
week: '%H:%M:%S',
month: '%H:%M:%S',
year: '%H:%M:%S'
},
opposite: true
}],
plotOptions:
{
series:
{
dataLabels:
{
enabled: true,
formatter: function()
{
if( this.series.index == 0 )
{
return secondsTimeSpanToHMS(this.y/1000) ;
}
else
{
return this.y;
}
}
}
}
},
series:
[{
}]
});
});
(I am doing this with django, html and js)
If anything is unclear please say so and I will try to explain it in further detail.
Thanks in advance for any replies.
Here is my proposal for the solution. I think that everything is explained in the comments. If something is unclear, feel free to ask.
let data1 = {
Jarnvag_asdasd: ['2020-10-22'],
Fiber_Matning: ['2020-10-28', '2020-10-29'],
Fiber_Forarbete: ['2020-10-28', '2020-10-29'],
};
let data2 = {
Jarnvag_asdasd: [28800],
Fiber_Matning: [28800, 18000],
Fiber_Forarbete: [28800, 14400],
};
// The constructor to create the series structure
function CreateSeries(name, data) {
this.name = name;
this.data = data;
}
// series array
let series = [];
// Iterate through the data to concat them
for (let i in data1) {
let data = [];
data1[i].forEach((d, j) => {
data.push([d, data2[i][j]])
})
series.push(new CreateSeries(i, data))
}
Highcharts.chart('container', {
series: series
});
Demo: https://jsfiddle.net/BlackLabel/r7ame5gw/

How to add text to chart.js data?

I need help to add a text after the data that shows the graph, the code I have is the following:
var ctx = document.getElementById("chart-area");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["label1", "label2", "label3", "label4"],
datasets: [{
data: [ 10, 20, 30, 40 ]
}]
}
}
It shows me the information like this:
label1: 10
But i need to add text after that, something like:
label1: 10 Mb
Please, I don't know how to add it, I already tried several ways
ChartJs does not provide any format label feature you have to play with it.
Initialize chart configuration with empty array then update it when you pushing data.
From this reference https://github.com/chartjs/Chart.js/issues/2738
here is fiddle link: http://jsfiddle.net/qsnpsxz5/7/
chart.config.data.labels.push("A label");
chart.config.data.labels.push("A label2");
chart.config.data.datasets[0].data.push(10);
chart.config.data.datasets[0].data.push(20);
chart.update();
Try using this script
var ctx = document.getElementById("chart-area");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["label1", "label2", "label3", "label4"],
datasets: [
{ data: [ 10, 20, 30, 40 ] }
]
},
options: {
tooltips: {
enabled: true,
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label;
var val = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
return label + ' : ' + val + ' Mb';
}
}
}
}
});

JSON api timestamp + data parsing

I'm making a chart using Highcharts.js
The API I'm using has a different output than what Highchart uses.
Highchart reads JSON data as [timestamp, data]
which looks something like this: [1512000000000,171.85],
furthermore, the rest of the data is parsed within the same call.
Now MY Api outputs data by a single call for each timestamp (via url &ts=1511929853 for example
outputs {"ENJ":{"USD":0.02154}} (the price for that point in time)
Now here's where things get complicated. I would need to parse the price from a certain date, till now.
I've already made a ++ variable for the timestamp, but how would I include the timestamp and the price for that timestamp within the array for the data output.
It's a bit confusing, as the calls would have to be repeated so many times to draw a historical graph of the price. Some help would be appreciated. If you need more clarification, I'm right here.
Data is parsed via data function
full code here
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime()/1000);
function count() {
if (startDate != endDate) {
startDate++
}
else {
return false;
}
};
count();
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function (data) {
// Create the chart
var enjPrice = `${data.ENJ.USD}`;
console.log(enjPrice);
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data: JSON.parse("[" + enjPrice + "]"),
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
});
You can use spread operator, like this,
let var = [new Date().getTime(), { ...data }.ENJ.USD]
This will result [1512000000000, 171.85] as you expected.
You need to make different functions for getting the data and generating the chart. Below is an example of how would you do it.
var startDate = 1511929853;
var endDate = Math.floor((new Date).getTime() / 1000);
var data = [];
function count() {
if (startDate != endDate) {
data.push(getPrice(startDate));
startDate++;
} else {
generateChart();
}
};
count();
function getPrice(timestamp) {
$.getJSON('https://min-api.cryptocompare.com/data/pricehistorical?fsym=ENJ&tsyms=USD&ts=' + startDate, function(data) {
return [timestamp, data.ENJ.USD];
});
}
function generateChart() {
Highcharts.stockChart('container', {
xAxis: {
gapGridLineWidth: 0
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1D'
}, {
type: 'all',
count: 1,
text: 'All'
}],
selected: 1,
inputEnabled: false
},
series: [{
name: 'AAPL',
type: 'area',
data,
gapSize: 5,
tooltip: {
valueDecimals: 2
}
}]
});
}
Though this is not the best way how you would do it but you get an idea.
I managed to solve the problem, by using a different API, which indexes data for past 30 days. I iterated into each index, 31, of them and grabbed the time and high(price) values and parsed them into a number since I was getting a "string" and then looped them into an array and put them into the final data [array]. just what I needed for the chart to work. If anyone needs any help just ask away. :) PS: Excuse the console.logs as I was using them to debug and test which helped me tremendously, you can remove them, as shall I
$.getJSON('https://min-api.cryptocompare.com/data/histoday?fsym=ENJ&tsym=USD', function(data) {
var x = `${data.Data[0].time}`;
var y = `${data.Data[0].high}`;
console.log(x);
console.log(y);
var tempData = [];
console.log(tempData);
for (var i = 0; i < 31; i++ ) {
var a = `${data.Data[i].time}`;
var b = `${data.Data[i].high}`;
function numberfy(val){
parseFloat(val);
}
a = parseFloat(a);
a = a * 1000;
b = parseFloat(b);
x = [a , b];
tempData.push(x);
};
data = tempData;
console.log(data.length);
Highcharts.stockChart('container', {

Displaying a json file with highstock

I have some difficulties displaying a graph with Highstock. It seems like I can't have access to the x-axis part where the graph should be displayed. I am new with Highstocks so my code could seem like a mess but my idea was the following:
First access the json file from the server. Convert it in the right format [[datestamp, value], ....]. Then display the graph.
Here is my Json file (file.json):
[{"date":"2013-10-04T22:31:12.000Z","value":30000},{"date":"2013-10-04T22:31:58.000Z","value":35000},{"date":"2013-10-04T22:32:05.000Z","value":60000},{"date":"2013-10-04T22:32:12.000Z","value":45000}]
My code is the following:
$(function() {
chartOjb = new Object();
var mydata = [];
$.getJSON('file.json', function(data) {
$.each(data, function (index, item) {
chartOjb.name = getTimestamp(item.date);
chartOjb.data = item.value;
mydata.push({ x: chartOjb.name, y: parseFloat(chartOjb.data) });
});
$('#container').highcharts('StockChart', {
chart: {
type: 'candlestick',
zoomType: 'x'
},
navigator: {
adaptToUpdatedData: false,
series: {
data: mydata
}
},
scrollbar: {
liveRedraw: false
},
xAxis: {
type: 'datetime',
title: 'Time',
//minRange: 3600 * 1000/15 // one hour
},
rangeSelector : {
selected : 1
},
title : {
text : value
},
series : [{
name : 'Capacité',
data : data,
tooltip: {
valueDecimals: 2
}
}] }); });
});
Thank you very much for your help
Could you add your function getTimestamp()? Maybe there is something wrong.
Keep in mind that:
x-value should be timestamp,
when using a lot of objects { x: x, y: y }, set turboThreshold

Highcharts load pointStart from JSON. Milliseconds to UTC time?

I made a graph with Highcharts which series is loaded from JSON.
I am bit new to handle JSON file though...
I want Highcharts to show date (in formart: YYYY/MM/DD ie.2013/04/01) on label of xAxis.
As far as I know, since I cannot write something like this in JSON,
"pointStart": [Date.UTC(2013, 4, 1)]
I wrote milliseconds instead.
My JSON:
[
{
"yAxis": 0,
"type": "column",
"name": "Y label",
"data": [0,0,153,179,122,126,120,101,110,95,142,88,82,92,115,101,141,162,0,0,0,0,0,7,6,0,10,0,9,4,56,86,66,61,87,72,74,60,83,74,50,73,61,56,90,78],
"pointStart": 1364774400000,
"pointInterval": 86400000
},{
"yAxis": 1,
"type": "line",
"name": "Y label 2",
"color": "#AA4643",
"data": [4980,4572,5554,6147,5268,5221,5263,5084,4906,5000,5198,4777,4790,4549,4158,4294,4891,4689,4432,3925,3708,3723,3623,3831,3787,4353,4809,5046,4989,4815,4315,4556,4502,4725,4537,4540,4654,4367,4589,4874,4837,5032,5046,4633,4561,4576],
"pointStart": 1364774400000,
"pointInterval": 86400000
}
]
And my javascript:
var options = {
chart: {
renderTo: 'container'
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%Y/%m/%d'
},
labels: {
rotation: -45,
align: 'right',
formatter: function() {
return Highcharts.dateFormat('%Y/%m/%d', this.x); //this returns invalid date.
}
},
title: {
text: ''
}
},
...
$.getJSON('test.json', function(data) {
options.series = data;
chart = new Highcharts.Chart(options);
});
This results invalid date on xAxis label.
But if I remove this part
formatter: function() {
return Highcharts.dateFormat('%Y/%m/%d', this.x);
}
returns no error but results like 1. Apr which I do not desire to show :(
Any solution to this?
Thank you.
I came up with solution as follows:
dateTimeLabelFormats: {
day: '%Y/%m/%d'
},
labels: {
rotation: -45,
align: 'right',
formatter: function() {
var _date = new Date(this.value),
_y = _date.getFullYear();
_m = _date.getMonth() + 1,
_d = _date.getDate(),
_result = _y + '/' + (_m < 10 ? "0"+_m : _m) + '/' + (_d < 10 ? "0"+_d : _d);
return _result;
}
},
...
put milliseconds value to Date object in which I was able to handle value w/ such methods as getFullYear(), getDate().
Thanks.
You have the date/time format wrong. It's not day: '%Y/%m/%d', it needs to be day: '%Y/%y/%e' see dateTimeLabelFormats Highcharts API reference.
You can use http://api.highcharts.com/highcharts#xAxis.labels.formatter and Highcharts.dateFormat() http://api.highcharts.com/highcharts#Highcharts.dateFormat()
labels: {
formatter: function() {
return Highcharts.dateFormat('%Y/%m/%d',this.value);
}

Categories

Resources