Input data in german data format combined with ChartsJs - javascript

I'm relative new to Charts.js, but I'll need it to create some nice graphs for my webpage. In the background I have a Django project running which computes me a certain amount of numbers. Since I've put the language code in Django to "de-at" (requirement, since there are some input variables to fill in by austrian users), the number formats are done like: "1.000.000,54€" and not the US-way like "1,000,000.54€".
If I now want to add some of my data into charts.js, it won't read the data, which has more than 6 digits. Furthermore, if there is a number like "653.598,36" it takes actually two parameters, namely (653,598 ; 36).
Formatting the numbers in python does not help, since charts.js won't use strings for the graphs. Using the setting "locale = 'de-DE'" in the charts.js options only helps for labelling propertes, not for the data itself.
If I change the Django setting back to "en-us", charts.js works with the numbers, but than my numbers on the webpage are not formatted correctly for the end-user.
Has someone experienced this problem and has a solution to it?
Thank you and best regards!
Here is the code of charts.js with example values. I used chart.js directly in a HTML-file.
Note: The numbers in the data-section are just examples. Usually, there is a variable in it, which has the value.
<canvas id="testChart" width="200" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<script>
var ctx = document.getElementById('testChart').getContext('2d');
var testChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['+', '-'],
datasets: [{
label: 'Years 1 - 20',
data: [ 568.987,68, 0],
backgroundColor: [
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(54, 162, 235, 0.2)'
],
borderWidth: 1
}, {
label: 'Einnahmen nach 20',
data: [ 1.265.986,32 , 0],
backgroundColor: [
'rgba(255, 99, 132, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 0.2)'
],
borderWidth: 1
},{
label: 'EK',
data: [0, 120.000,00],
backgroundColor: [
'rgba(200, 50, 132, 0.2)'
],
borderColor: [
'rgba(200, 50, 132, 0.2)'
],
borderWidth: 1
}, {
label: 'FK',
data: [0, 480.000,00],
backgroundColor: [
'rgba(150, 20, 132, 0.2)'
],
borderColor: [
'rgba(150, 20, 132, 0.2)'
],
borderWidth: 1
}
]
},
options: {
plugins: {
title: {
display: true,
text: 'Testgrafik'
},
},
locale: 'de-DE',
responsive: true,
scales: {
x: {
stacked: true,
},
y: {
stacked: true
}
}
}
});
</script>

Before inserting the numbers in that library, do this:
EDIT2: I misread your question, I thought you were asking how to change the floating point integers formats.
let n = "653.598,36";
let result = "";
let decimalPart = n.split(",")[1];
let decimalPartLen = decimalPart.length;
n = n.replace(".",""); //parseFloat doesn't like commas
let commaIndex = n.length - decimalPartLen;
result = parseFloat(n.substr(0,commaIndex - 1)+"."+n.substr(commaIndex, n.length));
console.log(result);
EDIT: this is client side js, but you could do this in python with minimal changes
Here it is in python:
n = "653.598,36"
result = ""
decimalPart = n.split(",")[1]
decimalPartLen = len(decimalPart)
n = n.replace(".","")
commaIndex = len(n) - decimalPartLen
result = float(n[:commaIndex-1]+"."+n[commaIndex:])
print(result)

Related

Trying to insert another label for a piechart in ChartsJS

I created this piechart using chartsjs. As of now, if you run the snippet, I am able to display my labels the following way:
Uno\Company 1
19
(56%)
However, I would love to display Company text underneath, so that it can be displayed like this:
Uno
Company1
19
(56%)
I tried creating a separate array: label2: ["Company1", "Company2", "Company3"]
Then in the callback, I added a new function, which i thought would give me the other label beneath, but no luck. Here is the code I used for that:
title2: function(tooltipItem, data, label2){
return data['label2'][tooltipItem[0]['index']]
}
Can anyone help me out?
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
label1: ["Uno\\Company1", "Dos\\Company2", "Tres\\Company3"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)'
],
borderWidth: 1
}]
},
options: {
tooltips: {
callbacks: {
title: function(tooltipItem, data, label1, label2) {
return data ['label1'][tooltipItem[0]['index']];
},
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']];
},
afterLabel: function(tooltipItem, data) {
var dataset = data['datasets'][0];
var percent = Math.round((dataset['data'][tooltipItem['index']] / dataset["_meta"][0]['total']) * 100)
return '(' + percent + '%)';
}
},
backgroundColor: '#FFF',
titleFontSize: 16,
titleFontColor: '#0066ff',
bodyFontColor: '#000',
bodyFontSize: 14,
displayColors: false
}
}
});
<div>
<canvas id="myChart" height="100"></canvas>
<div id="chartjs-tooltip">
<table></table>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js">
</script>
Simply change label1 from an array of strings to an array of arrays:
label1: [["Uno", "Company1"], ["Dos", "Company2"], ["Tres", "Company3"]]
Chart.js will treat separate array items as separate lines.

Creating categories with different widths in chart.js

I'm creating a line diagram using chart.js, and my X axis is of type category (which, in my case, makes absolute sense). Now, chart.js creates all categories with the same width, which I guess is a reasonable default.
However, I would like to have categories of different width, e.g.: The first category should be 3 times as wide as the second one, and the third one should be 2 times as wide as the second one, essentially rendering something such as:
| | | |
| | | |
| | | |
A B C
Is this possible? If so, how?
Have you tried using: dataset.barPercentage?
I used scale 1.0 to represent 3.0 and made the other ones relative to that scale.
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: '# of Votes',
data: [3, 4, 2],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)'
],
borderWidth: 1,
barPercentage: [
1.0,
0.333,
0.667
]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css" rel="stylesheet" />
<canvas id="myChart" width="400" height="200"></canvas>

Tick label overlaps axis label

ChartJS v2
I am having a problem on small screen sizes (using the iPhone 5 screen emulator in Chrome) with my X axis tick labels overlapping my X axis label.
My Y axis label is also being cut off.
I have tried playing around with padding and lineHeight for Label 2 to no avail. I have also tried setting the max / min rotation values for the X axis tick labels to 90deg which makes the issue worse.
The example in the screenshot above uses these settings:
var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
// The type of chart we want to create
type: "bar",
// The data for our dataset
data: {
labels: [
"0k-40k",
"40k-80k",
"80k-100k",
"100k-120k",
"120k-160k",
"160k-180k",
"180k-220k"
],
datasets: [
{
label: "My First dataset",
backgroundColor: "rgb(255, 99, 132)",
borderColor: "rgb(255, 99, 132)",
data: [0, 10, 5, 2, 20, 30, 45]
}
]
},
// Configuration options go here
options: {
legend: {
display: false
},
scales: {
xAxes: [
{
ticks: {
autoSkip: false,
fontSize: 16,
fontStyle: "bold",
precision: 2,
suggestedMin: 0
},
scaleLabel: {
display: true,
fontSize: 16,
fontStyle: "bold",
labelString: "Chart Label X",
}
}
],
yAxes: [
{
ticks: {
fontSize: 16,
fontStyle: "bold",
precision: 2,
suggestedMin: 0
},
scaleLabel: {
display: true,
fontSize: 16,
fontStyle: "bold",
labelString: "Chart Label Y",
}
}
]
}
}
});
This looks like it is probably a bug in ChartJS not calculating the label heights correctly when rotated. Has anybody else had this problem? Is there a work around?
Codepen: https://codepen.io/afisher88/pen/mayvoe
GitHub Issue: https://github.com/chartjs/Chart.js/issues/5906
In the end I had to compromise and shrink the font size, removing the x and y labels and updating the legend to provide the detail needed.
var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
// The type of chart we want to create
type: "bar",
// The data for our dataset
data: {
labels: [
"0k-40k",
"40k-80k",
"80k-100k",
"100k-120k",
"120k-160k",
"160k-180k",
"180k-220k"
],
datasets: [
{
label: "My dataset x vs y",
backgroundColor: "rgb(255, 99, 132)",
borderColor: "rgb(255, 99, 132)",
data: [0, 10, 5, 2, 20, 30, 45]
}
]
},
// Configuration options go here
options: {
legend: {
display: true
},
scales: {
xAxes: [
{
ticks: {
autoSkip: false,
fontSize: 11,
fontStyle: "bold",
precision: 2,
suggestedMin: 0
}
}
],
yAxes: [
{
ticks: {
fontSize: 11,
fontStyle: "bold",
precision: 2,
suggestedMin: 0
}
}
]
}
}
});
https://codepen.io/afisher88/pen/XoNVNe
Different browsers can render the canvas image in many different ways. Small screen devices are not an exception. You can try your code with different browsers on normal screen to assert your claim.
Chart.js have many options you can use for your code. i.e. You can use “Chart.bundle.js” or “Chart.js” depending on your environment. The CSS you use can also affect how your chart is rendered on a canvas. The bundled build includes Moment.js in a single file. You should use this version if you require time axes and want to include single file.
For example:
<!DOCTYPE html>
<!--
pcharts.html
-->
<html>
<head>
<title>P Charts</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../public/css/main.css">
<script src="../lib/charts/Chart.bundle.js"></script>
<script src="../lib/jquery/jquery.js"></script>
<script src="../js/appcharts.js"></script>
</head>
<body>
<h1>Charts</h1>
<hr>
<br>
<div id="myCan">
<canvas id="myChart" width="100" height="100"></canvas>
</div>
<br>
<br><br><hr><br><br>
</body>
</html>
appcharts.js
/*
* appcharts.js
*
*/
var ctx;
var myChart;
var cdata = [0, 10, 5, 2, 20, 30, 45];
var lblX = ["0k-40k","40k-80k","80k-100k","100k-120k","120k-160k","160k-180k","180k-220k"];
function init(){
render();
};
function render(){
ctx = document.getElementById("myChart").getContext('2d');
myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lblX,
datasets: [{
label: 'My demo2 dataset.',
data: cdata,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
xAxes: [{
ticks:{
beginAtZero:true
},
scaleLabel:{
display: true,
labelString: "Chart Label X."
}
}],
yAxes: [{
ticks: {
beginAtZero:true
},
scaleLabel: {
display: true,
labelString: "Chart Label Y."
}
}]
}
}
});
};
//
//$(document).ready(function(){
// $("#myCan").hide("slow");
// $("#myCan").show("slow");
//});
//
window.onload = function(){
init();
};
//
//
Squeezing the big image in a small canvas is like squeezing big tomatoes in a small bottle. What will come out of that bottle is the tomato sauce and tomato seeds. Of course you can replant the tomato seeds if only and only if they are still OK. Orthographic projection do just that. You can render a big
image in a small screen by using orthographic projection technique. e.g. Positioning of the camera or distortion determines what the viewer will see or look at.
When you are using charts you are actually drawing an image and rendering it on a screen for the viewer to look at. You can get the latest version of chart.js by using: npm install chart.js --save or download it from: https://github.com/chartjs/Chart.js/releases/latest It comes with docs and samples.
To create a chart, we need to instantiate the Chart class. To do this, we need to pass in the node, jQuery instance, or 2d context of the canvas of where we want to draw the chart. Once you have the element or context, you're ready to instantiate a pre-defined chart-type or create your own.
Good luck.

Create a dynamic Bar graph using Chart.js where data is from database

I have been working on this issue a week and more but until now I am not able to achieve the right output for this.
I am working an online system where the data I project is from a database. I have a table for enrollment records in my database. Using Chart.js, I wanted to show a dynamic bar graph of the yearly enrollment. The bar graph works perfectly but it shows inaccurate result where the count does not match with the right year.
I noticed, that this happens because when a year is with no data, the other year fills this year, making the result wrong.
What will I do so that it will ignore empty year data or just set it to zero. I hope you can understand my problem, because I have been searching solutions about this but I can't find the right answer.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script>
var year = ['2000','2001','2002', '2003','2004','2005','2006','2007','2008','2009','2010','2011','2012','2013','2014','2015','2016','2017','2018','2019','2020'];
var female = <?php echo $female; ?>;
var male = <?php echo $male; ?>;
var entranceDataset = {
label: 'Female',
type: 'bar',
yAxesID : "y-axis-1",
data: female,
backgroundColor: 'rgba(0, 204, 0, 0.2)',
borderColor: 'rgba(0, 204, 0,1)',
borderWidth: 1
};
var dataset = [];
dataset.push(entranceDataset);
var exitDataset = {
label: 'Male',
type: 'bar',
yAxesID : "y-axis-1",
data: male,
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
};
dataset.push(exitDataset);
var ctx = $('#enrollcanvas');
mainThroughputChart = new Chart(ctx, {
type: 'bar',
data: {
labels: year,
datasets: dataset
},
options: {
scales: {
xAxes : [{
gridLines : {
display : false
},
scaleLabel: {
display: true,
labelString: 'Year'
}
}]
},
}
});
</script>

Chart.JS - show values on top of points

Good evening,
I'm trying to build a line chart that represents API response time. The problem is that I didn't find any solution in Chart.JS documentation. Is there any native solution or any solution using canvas api?
I want to get the chart looking like this:
Here is the code that I've used to generate the chart
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: hoursArrFirst,
datasets: [{
label: 'First Brand API',
data: timeArrProftit,
borderWidth: 1,
backgroundColor: [
'rgba(255, 99, 132, 0.05)',
'rgba(255, 159, 64, 0.05)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(255, 59, 64, 1)'
]
},{
label: 'Second Brand API',
data: timeArrSecond,
borderWidth: 1,
backgroundColor: [
'rgba(132, 255, 99, 0.05)',
'rgba(64, 255, 159, 0.05)'
],
borderColor: [
'rgba(32,155,99,1)',
'rgba(64,155, 59, 1)'
]
},{
label: 'Third Brand API' ,
data: timeArrThird,
borderWidth: 1,
backgroundColor: [
'rgba(32, 99, 255, 0.05)',
'rgba(64, 59, 255, 0.05)'
],
borderColor: [
'rgba(32, 99, 120, 1)',
'rgba(64, 59, 120, 1)'
]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
</script>
Call a function during and after animation
var options = {
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
function drawDatasetPointsLabels() {
ctx.font = '.9rem sans-serif';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
$(dataset.points).each(function(pdx,pointinfo){
// First dataset is shifted off the scale line.
// Don't write to the canvas for the null placeholder.
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}

Categories

Resources