Displaying JSON data with Chartjs - javascript

First up - most of my development experience is with the back end and, while I have plenty of programming experience in that context, I'm not that familiar with Javascript.
I have managed to produce a REST service that (via GSON) generates JSON populated with data from a database. This data includes a list of two values: a date and a double indicating a temperature for that date. An example of the generated JSON can be found here.
What I'd like to try and do is to take the data and display it in a line chart. I've been trying this with Chartjs with extremely limited success.
The code I'm currently using to try and get the chart working is:
var data = [{"2019-03-30":11.0},{"2019-03-31":10.2},{"2019-04-01":10.0}];
var ctx = document.getElementById("temperatureChart").getContext('2d');
var chart = new Chart(ctx, {
type: "line",
data: {
datasets: [
{
label: "2019",
data: data,
borderColor: "rgb(192,49,62)",
fill: false
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
title: {
display: true,
text: 'Temperature Averages'
}
}
});
As you can see - I've, for the moment, simply hard coded a few data values in an attempt to try and get it working. All this produces is a chart with nothing on the X Axis and the values -1.0 to 1.0 in .2 increments - screenshot at the bottom of this post.
Honestly, I've no idea how to proceed from here. Is Chartjs even a good choice for this? Starting to wonder if I've bitten off more than I can chew.

Since you also asked "Is Chartjs even a good choice for this?", here is a DevExtreme Charts example:
(modified from devExtreme's sample)
I modified your data from this: (as I mentioned in your question's comments)
[ { "2019-03-30" : 11.0 }, { "2019-03-31" : 10.2 }, { "2019-04-01" : 10.0 }]
to this:
[ { x: "2019-03-30", y: 11.0 }, { x: "2019-03-31", y: 10.2 }, { x: "2019-04-01", y: 10.0 }]
HTML:
<div class="dx-viewport demo-container">
<div id="chart-demo">
<div id="chart"></div>
<div class="options">
<div class="caption">Options</div>
<div class="option">
<span>Series Type</span>
<div id="types"></div>
</div>
</div>
</div>
</div>
CSS:
.options {
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
margin-top: 20px;
}
.option {
margin-top: 10px;
}
.caption {
font-size: 18px;
font-weight: 500;
}
.option > span {
margin-right: 10px;
}
.option > .dx-widget {
display: inline-block;
vertical-align: middle;
}
Javascript:
$(function(){
var chart = $("#chart").dxChart({
palette: "Violet",
dataSource: dataSource,
commonSeriesSettings: {
argumentField: "x",
type: types[0]
},
margin: {
bottom: 20
},
argumentAxis: {
valueMarginsEnabled: false,
discreteAxisDivisionMode: "crossLabels",
grid: {
visible: true
}
},
series: [
{ valueField: "y", name: "Temperature" }
],
legend: {
verticalAlignment: "bottom",
horizontalAlignment: "center",
itemTextPosition: "bottom"
},
title: {
text: "Daily Temperature Variations",
subtitle: {
text: "(Celsius)"
}
},
"export": {
enabled: true
},
tooltip: {
enabled: true,
customizeTooltip: function (arg) {
return {
text: arg.valueText
};
}
}
}).dxChart("instance");
$("#types").dxSelectBox({
dataSource: types,
value: types[0],
onValueChanged: function(e){
chart.option("commonSeriesSettings.type", e.value);
}
});
});
var dataSource = [ { x: "2019-03-30", y: 11.0 }, { x: "2019-03-31", y: 10.2 }, { x: "2019-04-01", y: 10.0 }];
var types = ["line", "stackedline", "fullstackedline"];

Related

Send graph values to Chart.js template with Python Flask

I'm trying to make a data visualizer with a Flask and Chart.js api. My application has the following structure:
API
api.py
templates
index.html
static
css
estil.css
js
chartjs.js
(...)
So my idea is to put all the charts in the same file, outside the html. My problem is that I don't know how to send the data that I read from the database with Flask to the chart.js template. Surely it is very easy, but it is the first time that I touch chart.js and javascript and it is resisting me a bit.
(PSEODUCODE)
Python flask api (api.py):
#app.route('/')
def index():
fruits = []
# SQLITE3 QUERY
return render_template("index.html", fruits = fruits)
HTML (index.html):
<canvas id="myChart"></canvas>
<script src="static/js/chartjs.js"
JS (chartjs.js):
const ctx2 = document.getElementById('myChart');
const background_color2 = ['#33a3ec', '#ff6384'];
new Chart(ctx2, {
type: 'doughnut',
data: {
labels: ['Orange', 'Pineaple'],
datasets: [{
data: [82, 38],
/*
* If I put it inside the HTML with <script>TODO</script>
* it works fine for me but if I do it here it doesn't show
* me the graphics:
* data: {% values %},
*/
backgroundColor: background_color2,
borderWidth: 10,
borderColor: "#fbfbfb"
}]
},
options: {
scales: {
display: false
},
animation: {
duration: 1000,
animateRotate: true,
render: false
},
plugins: {
title: {
display: true,
text: "Juice fruits"
},
legend: {
display: true,
position: 'bottom'
}
}
}
});
As always, after not coding for a few hours comes the answer. It occurred to me to create each graph inside a function (like this):
function chartFruitJuice(fruits) {
const ctx = document.getElementById('myChart');
const background_color = ['#33a3ec', '#ffce55', '#4ac1c1', '#ff00ff00'];
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Orange', 'Apple', 'Pineaple'],
datasets: [{
data: fruits,
backgroundColor: background_color,
borderWidth: 10,
borderColor: "#fbfbfb"
}]
}, options: {
scales: {
display: false
},
animation: {
duration: 1000,
animateRotate: true,
render: false
},
plugins: {
datalabels: {
display: true,
align: 'bottom',
backgroundColor: '#ccc',
borderRadius: 3,
font: {
size: 18,
},
},
title: {
display: true,
text: "Fruit juice"
},
legend: {
display: true,
position: 'bottom'
}
}
}
});
}
And in the HTML, pass the Flask values as parameters of said function:
<canvas id="myChart"></canvas>
<script>
charFruitJuice({{ fruits | tojson | safe }});
</script>

zing Charts is making web page slow and laggy

I am currently trying to plot around 200k data (Time and Frequency) on zing Chart. it does load the chart successfully but page gets very heavy and it lags a lot. Here is my code please guide me have I done any Mistake or how can I plot data without page getting laggy.
I am trying to draw 4 charts like this one same webpage different data (which is 200k+ values).
i get data from APi code ...
$.ajax({
type: 'GET',
cache: false,
url:url,
data: { startTime : '2022-07-25 10-40-12', endTime : '2022-08-22 17-41-14', tableName : tableName },
success: function (data, textStatus, jqXHR) {
drawTimeVSAngleChart(data[0], data[1],data[2]);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
after rec data i just call drawTimeVSAngleChart function
timeArray , cpuArray, memoryArray these are passed
my code
function drawTimeVSAngleChart(timeArray , cpuArray, memoryArray){
$('#lineChart').remove();
$('#canvas_div').append(
'<div id="lineChart" style="min-height: 400px; height: 500px; max-height: 500px; max-width: 100%;"></div>'
);
var configTimeAndAngle = {
"type": "line",
legend: {
layout: "1x2", //row x column // items means in one two we added two items as in legends
x: "35%",
y: "6%",
},
"preview":{
"live":true
},
'scale-x': {
zooming: true,
labels: timeArray,
'max-items':8,
'min-items':7,
item: {
'font-size':10
}
},
'scale-y': {
//zooming: true,
//values: "50:350:50",
guide: {
'line-style': "dotted"
},
item: {
'font-size':10
}
},
tooltip: {
text: 'Time : %kt (X) Freq : %vt (Y).',
alpha: 0.9,
backgroundColor: '#F44336',
borderColor: '#B71C1C',
borderRadius: 2,
borderWidth: 1,
padding: '5 10'
},
gui: {
behaviors: [
{
id: 'DownloadPDF',
enabled: 'none'
},
{
id: 'ViewDataTable',
enabled: 'none'
},
{
id: 'ViewSource',
enabled: 'none'
},
{
id: 'ZingChart',
enabled: 'none'
},
{
id: 'CrosshairHide',
enabled: 'all'
}
]
},
"series": [{
"values": cpuArray,
'line-color': "#3366ff",
'background-color': "#3366ff",
text: "CPU Array"
},
{
"values": memoryArray,
'line-color': "#00cc99",
'background-color': "#00cc99",
text: "Memory Array"
}
]
};
zingchart.render({
id: 'lineChart',
data: configTimeAndAngle,
height: "100%",
width: "100%"
});
}
this solution is similar to #lasabahebwa solution but its actual solution which I was looking for. I am able to plot 1 million points without any issue. There is a issue from data been plotted. Issue is that when I load chart or apply filter chart takes around 9 seconds to load data. well my solution is
my solution is abit different because I am giving data in different format and time array is used. for details read question.
$('#lineChart_f').remove();
$('#canvas_div_f').append(
'<div id="lineChart_f" style="min-height: 400px; height: 550px; max-height: 500px; max-width: 100%;"></div>'
);
var configTimeAndAngle = {
"type": "line",
noData:{
text:"No data found",
backgroundColor: "#20b2db"
},
legend: {
layout: "1x2", //row x column // items means in one two we added two items as in legends
x: "35%",
y: "6%",
},
"preview":{
"live":true
},
plot: {
mode: 'fast',
},
'scale-x': {
zooming: true,
labels: timeArray,
item: {
'font-size':10
}
},
'scale-y': {
'auto-fit': true,
'min-value':30,
'max-value':70,
guide: {
'line-style': "dotted"
},
item: {
'font-size':10
}
},
'crosshair-x': {
text: 'Time : %kt (X) Freq : %vt (Y).',
'line-style': 'dashed',
'line-width': 2,
'line-color': '#2196F3',
marker: {
type: 'triangle',
size: 5,
visible: true
}
},
gui: {
behaviors: [
{
id: 'DownloadPDF',
enabled: 'none'
},
{
id: 'ViewDataTable',
enabled: 'none'
},
{
id: 'ViewSource',
enabled: 'none'
},
{
id: 'ZingChart',
enabled: 'none'
},
{
id: 'CrosshairHide',
enabled: 'all'
}
]
},
"series": [{
"values": frequency_array_ff,
'line-color': "#3366ff",
'background-color': "#3366ff",
text: "Centeral Frequency"
},
{
"values": frequency_array_fh,
'line-color': "#00cc99",
'background-color': "#00cc99",
text: "Frequency Hopping"
}
]
};
zingchart.QUOTEDVALUES = true;
zingchart.render({
id: "lineChart_f",
height: "100%",
width: "100%",
output: "canvas",
data: configTimeAndAngle
});
unfortunately the current library gets slower as you get into larger datasets (20k+ nodes). How do we combat this? Well, there is no straightforward solution to performance but there are some basic steps you can take to achieve a relative performance gain, such as any combination of the following methodologies.
It's also worth noting that ZC3 does 1M data in under 0.1s but unfortunately it's not ready for public.

Chart JS : Display the percentage of labels without getContext('2d')

I'm using the library chartJs to display the data that i get from my MySQL database.
In the fucntion below, AddValuesToNavigatorChart takes the browsers data and the percentage data and displays them on the pie chart.
What i need to know, is how to add '%' in my labels ?
I found few answer with getContent('2d').. using the old way, but it's not working.
This is the function :
function AddValuesToNavigatorChart(browsers, percentage) {
checkNavigatorChart()
const data = {
labels: browsers,
datasets: [{
data: percentage,
backgroundColor: [
'rgb(192,192,192)',
'rgb(255,0,0)',
'rgb(0,0,0)',
'rgb(105,105,105)'
],
hoverOffset: 4
}]
};
const config = {
tooltips: {
enabled: false
},
type: 'pie',
data: data,
plugins: [ChartDataLabels],
options: {
showTooltips: false,
plugins: {
datalabels: {
color: 'rgb(255,255,255)',
borderWidth: '2',
align: 'top'
},
legend: {
position: 'bottom',
align: 'center',
labels: {
boxWidth: 12,
padding: 15,
usePointStyle: true,
pointStyle: 'circle'
}
},
title: {
text: 'Navigator Chart',
display: true,
color: 'rgb(0,0,0)',
position: 'top'
}
}
}
};
const NavigatorChart = new Chart(
document.getElementById('NavigatorChart'),
config
);
}
Please provide the version of chartjs that you are using.
Did you mean you want to show the % in the label of the tooltip?
For version v3.8.0, here is a working code I have just made, Link
As in option, you can edit the label of tooltip as you want:
options: {
plugins: {
tooltip: {
callbacks: {
label: (tooltipItem) => {
//tooltipItem is for the slice of the pie you are hovering now
return ' ' + tooltipItem.parsed + '%';
},
}
}
}
}

Line in C3.js goes out of the chart area

I am facing a bug in C3.js chart library. When you look at the image you can see that the line chart goes out of the "chart-area" and it is not visible in some peak-cases. I would omit the thing that the label is not visible but I would be happy to see the line without hidden parts.
Here is a config for reproducing the error:
const config = {
x: {
tick: {
rotate: -45,
format: '%Y-%m-%d %H:%M:%S'
},
type: 'timeseries',
height: 85,
padding: {left: 30}
},
y: {
label: {position: 'outer-middle', text: 'Event count'},
min: 0,
padding: {top: 0, bottom: 0}
}
},
bindto: '#single-chart',
color: {pattern: ['#323f71']},
data: {
x: 'x',
xFormat: '%Y-%m-%d %H:%M:%S',
labels: true,
type: 'area-spline'
},
legend: {show: false},
size: {height: 380},
padding: {
right: 50,
left: 80
},
grid: {
y: {
show: true
}
}
};
Does anybody now, how to fix this?
I think the answer is to related to the axis.y.padding.top = 0 setting. However, my example looks slightly different from yours in that I never lose the line plot. The only way I can replicate yours is to set axis.y.max=1400, which then does chop the top of the plot off. If not then please could you unhide the y-axis line and post another image because it will be useful to see if the line terminator tick is there at the top of the axis.
See working snippet below which is modelled on your code and case but not exactly the same as slightly re-written. The button toggles between y.top padding of 20 and zero to illustrate the effect. You can see the highest plot point label becoming clipped off by the top limit. You may want to experiment with removing the setting entirely.
// Cannot find a usable method for changing axis.y.padding.top so redrawing the chart to show effect.
function resetIncPadding(yPaddingTop){
var chart = c3.generate(
{
bindto: '#chart',
size: {
width: 600,
height: 200
},
data: {
x: 'x',
// xFormat: '%Y-%m-%d %H:%M:%S',
labels: true,
type: 'area-spline',
columns: [
['x',
'2018-01-01','2018-01-02','2018-01-03','2018-01-04','2018-01-05','2018-01-06','2018-01-07','2018-01-08','2018-01-09','2018-01-10','2018-01-11','2018-01-12','2018-01-13','2018-01-14','2018-01-15','2018-01-16','2018-01-17','2018-01-18','2018-01-19','2018-01-20','2018-01-21','2018-01-22','2018-01-23','2018-01-24','2018-01-25','2018-01-26','2018-01-27','2018-01-28','2018-01-29','2018-01-30','2018-01-31'
],
['y', 5,10,15,10,10,10,10,5,30,90,500,1000,1200,1500,1230,1110,620,80,30,10,5,15,5,5,15,5,15,12,15,10,10
]
]
},
color: {pattern: ['#323f71']},
axis: {
x: {
type: 'timeseries',
tick: {
rotate: -45,
format: '%Y-%m-%d %H:%M:%S'
},
height: 85,
padding: {left: 30}
},
y: {
label: {position: 'outer-middle', text: 'Event count'},
min: 0,
padding: {top: yPaddingTop, bottom: 0}
}
},
legend: {show: false},
padding: {
right: 50,
left: 80
},
grid: {
y: {
show: true
}
}
});
}
// this is all about toggling the padding.
$('#toggle').on('click', function(e){
val = $(this).val();
val = (parseInt(val,10) === 20 ? 0 : 20);
$(this).val(val).html(val)
resetIncPadding(val);
console.log(val)
})
// first draw on startup
resetIncPadding(20);
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.7/c3.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.7/c3.min.js"></script>
<p>Using axis.y.padding.top = <button id='toggle' value='20'>20</button></p>
<div class='chart-wrapper'>
<div class='chat' id="chart"></div>
</div>

Inefficient functions - how to assign colour to datapoints in Highchart

I am trying to create a progress bar for surveys. Depending on the progress, I would like to assign colors dynamically to each data point. I have managed this, but it seems that the functions takes ages to run. At least, that is my interpretation as I am new to much of this.
So my question is: How can I assign colors to the data points more effectively? I am not sure how to reference to the different colors within Highcharts if I create and store multiple colors in one function.
http://jsfiddle.net/oskjerv/v4Lx69Lv/
Hope my question makes sense to some/any of you.
All the best.
Highcharts.chart('container', {
chart: {
type: 'bar'
},
title: {
text: ''
},
xAxis: {
categories: [''],
visible:false,
},
yAxis: {
min: 0,
visible:false
},
legend: {
reversed: true,
enabled:false
},
plotOptions: {
series: {
stacking: 'normal',
animation:false
}
},
labels: {
enabled: false
},
tooltip: {
enabled: false
},
exporting:{
enabled:false
},
credits:{
enabled:false
},
series: [{
name: 'Del1',
data: [.20],
color: getColourFirst()
}, {
name: 'Del2',
data: [.20],
color: getColourSecond()
}, {
name: 'Del3',
data: [.20],
color: getColourThird()
},
{
name: 'Del4',
data: [.20],
color: getColourFourth()
},
{
name: 'Del4',
data: [.20],
color: getColourFifth()
}]
});
function getColourFirst(){
var colour1=['#D5D4D4'];
return colour1;
}
function getColourSecond(){
var colour2=['#D5D4D4'];
return colour2;
}
function getColourThird(){
var colour3=['#87bdd8'];
return colour3;
}
function getColourFourth(){
var colour4=['#87bdd8'];
return colour4;
}
function getColourFifth(){
var colour5=['#87bdd8'];
return colour5;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 310px; max-width: 200px; height: 100px; margin: 0 auto"></div>
The main problem here is that you are saying color: ['#87bdd8']. This is not a valid format. In short you are looking for color: '#87bdd8' instead. See this updated JSFiddle for a demo, and see the Colors description for more detail on the syntax.
When it comes to how to solve the colors there are a million ways to do it, but I'd probably suggest something that uses an index instead of all separate unautomatable function names. For example:
myColors = ['#D5D4D4','#D5D4D4','#87bdd8','#87bdd8','#87bdd8'];
function getColor(index) {
return myColors[index%myColors.length];
}
Or see this JSFiddle demonstration.

Categories

Resources