ChartJS not displaying time data using Moment.js - javascript

I am trying to map out a series of data points on a given day by the hour.
Not every hour is included in the data set, however I still want to show the time from 0:00 - 23:00 and plot the data points that is available.
My error is
This method is not implemented: either no adapter can be found or an
incomplete integration was provided.
However, Looking at the documentation and this tutorial, I still get the error.
In my hourlyData set, x is the hour and y is the amount.
Can anyone see what I am doing wrong?
$(document).ready(function() {
var ctx = document.getElementById('chart_hourlycalls').getContext('2d');
var hourlyData = [{
"x": "1",
"y": "1"
}, {
"x": "3",
"y": "2"
}, {
"x": "5",
"y": "1"
}, {
"x": "6",
"y": "13"
}, {
"x": "7",
"y": "13"
}, {
"x": "8",
"y": "5"
}, {
"x": "9",
"y": "9"
}, {
"x": "10",
"y": "14"
}, {
"x": "11",
"y": "24"
}, {
"x": "12",
"y": "5"
}];
var labels = hourlyData.map(e => moment(e.x, 'HH'));
var data = hourlyData.map(e => e.y);
var options = {
scales: {
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Calls'
},
ticks: {
beginAtZero: true
}
}],
xAxes: [{
type: 'time',
time: {
unit: 'hour',
displayFormats: {
hour: 'HH a'
}
},
display: true,
scaleLabel: {
display: true,
labelString: 'Hour'
}
}]
},
tooltips: {
enabled: true
},
};
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
data: data
},
options: options
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<canvas id="chart_hourlycalls"></canvas>

I solved it by adding:
import { Chart } from 'chart.js';
import 'chartjs-adapter-moment';
as pointed out by the doc

You need to include Moment.js before Chart.js.
The Chart.js documentation could do a better job of highlighting this, but it is explained on the installation page:
The stand-alone build includes Chart.js as well as the color parsing library. If this version is used, you are required to include Moment.js before Chart.js for the functionality of the time axis.

You could try to put the moment.js script above the chart.js. However here is an example of using moment.js that may help you.
https://stackoverflow.com/a/58555196/12176979

Related

How make more advanced charts in node-red? How can I make live chart in Node-red with two or more y axis?

I have problem with make more advanced live chart. I use node-red on PC to collect data from PLC and display it in line chart using standard node-red dashboard chart node. PLC read values from 30 sensors: 20 preassure, 3 temperature, 3 flow, 1 speed. Read frequency is 4Hz. Not all values are visible at time, because I want chart to be clear. For this I need also split y axis according to sensors. So one for preassure, one for temperature, one for flow and one for speed. For now data is coming in form of array msg.payload[] but it is not important because I will format data to proper form. I know format data for live chart to work is
{topic:"temperature", payload:22}
{topic:"humidity", payload:66}
and for static chart
msg.payload =[{
"series": ["A", "B", "C"],
"data": [
[{ "x": 1504029632890, "y": 5 },
{ "x": 1504029636001, "y": 4 },
{ "x": 1504029638656, "y": 2 }
],
[{ "x": 1504029633514, "y": 6 },
{ "x": 1504029636622, "y": 7 },
{ "x": 1504029639539, "y": 6 }
],
[{ "x": 1504029634400, "y": 7 },
{ "x": 1504029637959, "y": 7 },
{ "x": 1504029640317, "y": 7 }
]
],
"labels": [""]
}]
.
standard chart with data from above code
I know node-red dashboard chart is similar to chart.js. I can send ui_control message to adjust actual y-axe and add two more y-axis:
let msg2=
{
ui_control :{
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'minute',
unitStepSize: 1,
displayFormats: {
minute: 'HH:mm'
}
}
}],
yAxes: [{
id: "1",
scaleLabel: {
display: true,
labelString: 'pressure [bar]'
},
ticks: {
min: -10,
max: 10,
stepSize: 2
}
}, {
id: "2",
scaleLabel: {
display: true,
labelString: 'Temperature [°C]'
},
ticks: {
min: 0,
max: 20,
stepSize: 4
}
}, {
id: "3",
scaleLabel: {
display: true,
labelString: 'Flow [L/min]'
},
ticks: {
min: 0,
max: 20,
stepSize: 4
}
}]
} ,
legend: {
display: true,
position: 'top',
},
title: {
display: true,
text: 'Chart'
}
,
animation: {
duration: 0
}
}},
};
return msg2;
Result is:
Same data, ui_control message result
And now I want display for example:
msg.payload = 5;
msg.topic="C";
msg.yAxis="3";
return msg;
and instead get "C" on axe 3 (temperature), I get it on axe 1 (pressure), and Node-red sometimes freeze after send above message.
chart with one data point on 1 y axe
So now proper question: How Can I use more than one y axis? Can I done this with standard node-red dashboard chart? How data structure should look for static chart, and how for live chart? Maybe I should use node-red template node and write code in HTML based on chart.js? And one last question, how can I minimalize PC usage, because when I run 30 sensors, at 4Hz, I get 1200 point in just 10s?
I will be grateful for your help :D

chart.js show time in series

I want to show the x values of a array as time stamp. The x value was generated by x = Date.now()
var test = {
"datasets": [{
"data": [{
"x": 1609753734252,
"y": 44.82420388241937
}, {
"x": 1609753735263,
"y": 46.02068615892796
}, {
"x": 1609753741254,
"y": 53.21622091958411
}]
}, {
"data": [{
"x": 1609753734252,
"y": 129.77634259930292
}, {
"x": 1609753735263,
"y": 129.86789675071483
}, {
"x": 1609753741254,
"y": 129.9137373479274
}]
},
"labels": [1609753734252, 1609753735263, 1609753741254]
}
The options
var config = {
type: 'line',
options: {
responsive: true,
responsiveAnimatinDuration: 500,
animation: {
duration: 0
},
elements: {
point: {
radius: 0
},
line: {
borderWidth: 2,
fill : false
}
},
legend : {
display : false
},
scales: {
xAxes: [{
type : 'time',
time : {
format : "HH:MM",
unit : "hour"
}
}]
}
}
};
The javascript code:
config.data = test;
window.myLine = new Chart(ctx.getContext('2d'), config);
I want to show the time in format hh:mm? What is wrong?
The data will be updated all 500 ms. Can I hide the transitions?
You don't have that option format as you're using it
You can use the unit and the parser, this last one accepts the same format options as moment accepts.
You can try using as a string like the following:
MM-DD-YYYY
Or sending a function, like this
parser: (tickValue) => {
// just as an example
if (tickValue > 0)
return moment(tickValue).format('MM-DD-YYYY');
}
Can you please try the following way mentioned here in the documentation to formate date
https://www.chartjs.org/docs/latest/axes/cartesian/time.html#display-formats.
I tried it with the following:
scales: {
xAxes: [{
type: 'time',
time: {
displayFormats: {
second: 'hh:mm:ss'
}
// unit : 'minute'
}
}]
Now I get all the years from 1971 to today. But I want to have the x-scaling set auto. Without displayFormat all times are displayed. But unfortunately as long int.
I also tried it with "unit". After that I get an exception: isAMomemtObject

Vue.js Realtime Chart with Websocket or Socket.io

I use vue.js for my project. Also I use websocket for my datas. Every one second come datas. I need to use realtime chart on my project. But I dont find any chart to solve my problem. For example I use apexchart but it have not refresh datas in my chart when new datas come.
my websocket data like:
{
"topic": "2",
"message": "data"
}
my database data like this:
{
"id": "1",
"deviceName": "refrigerator",
"deviceType": "lineChart",
"topic": "1",
"message": "",
},
{
"id": "8",
"deviceName": "refrigerator",
"deviceType": "lineChart",
"topic": "1",
"message": "",
},
I get my datas from database in this code. And I check my topic, is it same or not. if it is same, I put websocket message to json data to see at screen:
let bufferMessage = [];
bufferMessage = jsonFromDatabase;
socket.on("message", (topic, message) => {
bufferMessage.forEach(element => {
if (element.topic == topic) {
element.message = message.toString();
}
});
});
My code is :
<div id="chart">
<apexchart type="line" height="350" :options="chartOptions" :series="$store.state.bufferMessage[index].message"></apexchart>
</div>
<script>
import Vue from "vue";
import ApexCharts from "apexcharts";
import VueApexCharts from "vue-apexcharts";
Vue.component("apexchart", VueApexCharts);
export default {
components: {
apexchart: VueApexCharts,
},
data() {
return {
series: [
{
name: "Desktops",
data: [],
},
],
chartOptions: {
chart: {
height: 350,
type: "line",
zoom: {
enabled: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "straight",
},
title: {
text: "Product Trends by Month",
align: "left",
},
grid: {
row: {
colors: ["#f3f3f3", "transparent"],
opacity: 0.5,
},
},
xaxis: {
categories: [],
},
},
}
</script>
but the way there is no any error in this code. I just want to convert this chart to realtime chart for my websocket datas.
Unless OP shows the part in the code of updating the data, I only can offer a reference of the official apexcharts documentation, about updating the data :
import VueApexCharts from 'vue-apexcharts'
export default {
name: 'Vue Chart',
data: function () {
return {
chartOptions: {
chart: {
id: 'vuechart-example',
},
xaxis: {
categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998],
},
},
series: [{
name: 'Vue Chart',
data: [30, 40, 45, 50, 49, 60, 70, 81]
}]
}
},
methods: {
updateChart() {
const max = 90;
const min = 20;
const newData = this.series[0].data.map(() => {
return Math.floor(Math.random() * (max - min + 1)) + min
})
// In the same way, update the series option
this.series = [{
data: newData
}]
}
}
}
As you can see in the example above, by just changing the props, we trigger the update event of ApexCharts. (from the docs)
Sandbox Example https://codesandbox.io/s/50z5wrmp6k

Chart.js point format data for a scatter plot

Chart.js scatter chart only accepts data in a point format (x, y). Im a trying to fill the data points with infomration about medications from a file called meds.json
More specifically, the x would be the month of last fill date of the medication and the y would be the dose.
How can I grab all this data from the meds.json file and insert it to the data to create the points for my scatter plot?
If I try to grab all dates and store them in an array, and all the dose values in another array, how can I use that populate the point data using those arrays?
Here's how to make a scatter plot using Chart.js, I am trying to populate the x,y points under data 'data':
// charts.js
var scatterChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
label: 'Scatter Dataset',
data: [{
// x = month, y = dose
// fill these in for all meds in the json file
x: -10,
y: 0
}, {
x: 0,
y: 10
}, {
x: 10,
y: 5
}]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'top'
}]
}
}
});
}
meds.json
[
{
"name": "Simvastatin",
"dose": 10,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
},
{
"name": "Lisinopril",
"dose": 5,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
}
...... The list goes on
]
You should actually use a line chart for this which would be much more appropriate and exactly show the trend & relationship between month and the dosage.
But since you asked for scatter chart...you can do it like this :
const data = [{
"name": "Simvastatin",
"dose": 10,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
},
{
"name": "Lisinopril",
"dose": 5,
"dose unit": "mg",
"freq": "qd",
"route": "PO",
"last fill date": "2/15/2020",
"coverage": "100%",
"anticipated remaining fills": 2
}
]
const transformedData = data.map(obj=>{
return {
x:new Date(obj["last fill date"]).getMonth() + 1,
y:obj.dose,
}
})
console.log(transformedData)
and then use as
var scatterChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
label: 'Scatter Dataset',
data: transformedData
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'top'
}]
}
}
});
}
Hope this helps !

Tooltips displaying "rgb(0,0,0)" instead of label value on bar chart

I'm using the 2.0 (Alpha) version of Chart.js, and...
The tooltips of my bar chart display the string "rgb(0,0,0)" instead of the label value with the code above. You can see that this.data.labels contains numeric strings. If I change them to regular ints, they're being displayed fine after a strange effect where you see a lot of decimals changing so fast...
var ScoresFrequencyChartDrawer = function () {
this.data = {
labels: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
datasets: [{
backgroundColor: "rgba(150, 150, 150, 0.9)",
data: [1, 1, 2, 3, 7, 12, 15, 17, 23, 15, 10]
}]
};
this.options = {
events: ["mousemove"],
scales: {
xAxes: [{
display: true,
gridLines: {
drawOnChartArea: false
},
labels: {
fontSize: 15,
fontStyle: "bolder"
}
}],
yAxes: [{
display: false,
gridLines: {
drawOnChartArea: false
}
}]
}
};
this.chart = {};
}
ScoresFrequencyChartDrawer.prototype.draw = function() {
var canvas = document.getElementById("scores-frequency-chart");
var ctx = canvas.getContext("2d");
this.chart = new Chart(ctx, {
type: 'bar',
data: this.data,
options: this.options
});
}
The issue at github -> https://github.com/nnnick/Chart.js/issues/1261
I have fixed it with the code above...
// Adding this to the this.data.labels initialization
labels: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(eachToString),
// The eachToString function
function eachToString(el) {
return el.toString()+"%";
}
But as the bug it is, the issue at Github remains open.

Categories