Pagination in Bar chart using ChartJS - javascript

I am using chartJS for display some data with Bar Chart. there are some issues with chartJs. When i have to much data-filed for example 100 or more data-field and it have long lasting label its looks like ugly.
how to config bar chart ?
here is my bar chart screenshot
here is my FIDDLE
in above example i have 100 data-filed, can i paginate this bar-chart ?
here is my code
var lbl = [];
var dt = [];
for(var i = 1;i<=100;i++){
lbl.push("this_is_my_lable_name_"+i);
}
for(var i = 1;i<=100;i++){
dt.push(Math.floor((Math.random() * 100) + 1));
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lbl,
datasets: [{
label: '# of Votes',
data: dt,
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: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});

You can try this solution to consider the chart scroll like this:
Clone a different canvas for y axis so that when you scroll then only bars will appear to move
Adding the canvas for y axis
<canvas id="myChartAxis" height="600" width="0"></canvas>
Now cloning the axis
var sourceCanvas = myLiveChart.chart.canvas;
var copyWidth = myLiveChart.scales['y-axis-0'].width - 10;
var copyHeight = myLiveChart.scales['y-axis-0'].height + myLiveChart.scales['y-axis-0'].top + 10;
var targetCtx = document.getElementById("myChartAxis").getContext("2d");
targetCtx.canvas.width = copyWidth;
targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);
For a Demo see this FIDDLE
For better visualization its better to avoid labels in x axis and show this info intuitive via tool tip anyhow

You could wrap the canvas with a wrapper class and change its width accordingly which suites you the best. also, if you don't want the chart to cover entire screen, you can wrap it with another wrapper class.
var lbl = [];
var dt = [];
for (var i = 1; i <= 100; i++) {
lbl.push("this_is_my_lable_name_" + i);
}
for (var i = 1; i <= 100; i++) {
dt.push(Math.floor((Math.random() * 100) + 1));
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lbl,
datasets: [{
label: '# of Votes',
data: dt,
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: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
.wrapper {
width: 600px;
height: 400px;
overflow-x: scroll;
}
.chartWrapper {
width: 6000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="wrapper">
<div class="chartWrapper">
<canvas id="myChart" height="19"></canvas>
</div>
</div>
JSFiddle

Related

How to pass my array of objects into a graph with Chart.js

Hello I am trying to present my array of objects in a graph with Chart.js here is the code
let timers = {neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
var detection = new Chart(c, {
type: 'bar',
data: {
labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
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: 2,
data: timers,
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
The problem is that the graph does not take as labels the one that I am giving to it but instead it takes as labels the names from the object array and due to that I cannot resize the x labels to be bigger. Thanks in advance for any tips.
As per the chart js documentation, when you give a map (key,value) to data field like timers in your case, chart js automatically takes keys as labels and values as data points to be plotted.
So, if you want to give your own labels in spite of this, you can add following snippet to your existing code.
var keys = Object.keys(timers);
var values = keys.map(function(v) { return timers[v]; });
and pass values instead of timers.
Full code -
let timers = {neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
var keys = Object.keys(timers);
var values = keys.map(function(v) { return timers[v]; });
var detection = new Chart(c, {
type: 'bar',
data: {
labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
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: 2,
data: values,
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
Update:
As you want to update charts as timers are getting updated in setInterval, you have to put chart creation code also in setInterval function.
For example, you can refer to the following full html file
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js" integrity="sha512-Wt1bJGtlnMtGP0dqNFH1xlkLBNpEodaiQ8ZN5JLA5wpc1sUlk/O5uuOMNgvzddzkpvZ9GLyYNa8w2s7rqiTk5Q==" crossorigin="anonymous" referrerpolicy="no-referrer">
</script>
<script>
var i = 0;
setInterval(updateChart,3000);
function updateChart(){
var c = document.getElementById("myChart");
let chartStatus = Chart.getChart("myChart"); // <canvas> id
if (chartStatus != undefined) {
chartStatus.destroy();
}
i = i+1;
let timers;
if(i%2==0){
timers = {neutral: 20, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
}
else{
timers = {neutral: 0, happy: 20, sad: 0, angry: 0, surprised: 0, disgust: 0};
}
var keys = Object.keys(timers);
var values = keys.map(function(v) { return timers[v]; });
var detection = new Chart(c, {
type: 'bar',
data: {
labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
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: 2,
data: keys.map(function(v) { return timers[v]; }),
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
}
</script>
</head>
<button onclick="updateChart()">Update Chart</button>
<canvas id="myChart" width="100" height="100"></canvas>
You can run this html code for better understanding.
You just need to let the labels array out of the chart like so:
const ctx = document.getElementById('chartJSContainer').getContext('2d');
const timers = {
neutral: 10,
happy: 0,
sad: 0,
angry: 0,
surprised: 0,
disgust: 20
};
const detection = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
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: 2,
data: timers,
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>

Javascript and Chart.js not taking user input assuming it is a variable scope issue

Hey I have only been javascript for a little bit but I am trying to get user input so that it can split up that number into 50% 30% and 20% which will also display the percentages in a chart using chart.js. Now I have tried many different ways which either result in no chart, no output of the numbers in the div elements, or just nothing at all. I assume it has to deal with scope issues on the perfifty variables being in the function but then getDocumentById is not retrieving them when they are global and I still can't get those variables to be part of the chart. Sorry if this is a simple fix I have just been on this for too many days and I still cant figure it out. Thank you.
function calculate(){
var user_input = document.getElementById("monthlyincome").value;
var percentages = {
perfifty: (50 / 100) * user_input,
perthirty: (30 / 100) * user_input,
pertwenty: (20 / 100) * user_input
};
document.getElementById("50%").innerHTML = percentages.perfifty;
document.getElementById("30%").innerHTML = percentages.perthirty;
document.getElementById("20%").innerHTML = percentages.pertwenty;
};
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: '',
data: [percentages.perfifty, percentages.perthirty, percentages.pertwenty],
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: {
y: {
beginAtZero: true
}
}
}
});
I assume you call calculate when the user has given input and you create the chart outside of any function. This would mean you create the chart immediately when loading the script, when the user has not given any input yet. you want to create the chart inside calculate or if you want to see the canvas before user input, you can update the chart.
Here is an example:
function handleInput() {
let text = document.getElementById("uInput");
var num = Number(text.value);
if (isNaN(num)) {
alert("bad input!");
return;
}
var percentages = {
perfifty: (50 / 100) * num,
perthirty: (30 / 100) * num,
pertwenty: (20 / 100) * num
};
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: '',
data: [percentages.perfifty, percentages.perthirty, percentages.pertwenty],
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: {
y: {
beginAtZero: true
}
}
}
});
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.5.1/dist/chart.min.js"></script>
<label for="uInput">Input:</label>
<input type="text" id="uInput">
<button onclick="handleInput()"> Submit </button>
<canvas id="myChart"></canvas>

How to make chart for ethereum smart contract

I have here a smart contract and a I want to make a chart for this smart Contract address
0xE462CbEE0cd420f6c199B0194B1D8D93Fb5e7720 and for "total supply"
I want the chart to update as soon as a transaction goes in our out
How can i implement this in chartjs?
I have here the html canvas
<canvas id="myChart" width="400" height="400"></canvas>
and than the js file with this
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
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: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
//and here is the data from my smart contract
var supply = await contract.methods.totalSupply().call()
// and than i output it in my UI like this
document.getElementById('contractBalanceSnet').innerHTML = supply/100000000
How can i now use the data totalSupply for the chart?

Chart JS display Data Value on the top of the Bar

I m begginning with CHART JS and i've got a problem when i want to display the data Value on the top of each bar and the value disappear when my mouse is hover the bar. The next problem is the value are cropped on the top of the Chart
Here's my code :
function assignChart(ctx, dataArray) {
const dataLabel = ["Paris", "Milan", "London", "Florence", "New York", "Not specified"];
return (new Chart(ctx, {
type: 'bar',
data: {
labels: dataLabel,
datasets: [{
data: dataArray,
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: {
events: [],
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
display: false,
beginAtZero:true,
}
}]
},
animation: {
duration : 1,
onComplete : function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
if (dataset.data[index] > 0) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y);
}
});
});
}
}
}
}));
}
Ps : i'm using ChartJS 2.7.3
For the problem of yours the data labels getting cropped on the top, you can add padding to the through the layout option like this:
layout: {
padding: {
left: 0,
right: 0,
top: 15,
bottom: 0
}
}
See fiddle -> https://jsfiddle.net/xys1tqfn/1/

Prevent size of canvas chart js to equal window height and width

I am using chartjs to display data and the chart (canvas) takes up 100% width and 100% height of the window.
I want to reduce this to be 600px by 600px. To do this I tried using
Chart.defaults.global.legend.fullWidth = false; however this didn't work.
I have created a jsfiddle here for your convenience.
See code below:
HTML
<canvas id="myChart" width="400" height="400"></canvas>
JS
var ctx = document.getElementById("myChart");
Chart.defaults.global.defaultFontColor = "#000";
Chart.defaults.global.legend.fullWidth = false;
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: labels,
datasets: [{
label: '# of Followers',
data: followers,
backgroundColor: [
'rgba(255, 99, 132, 0.9)',
'rgba(54, 162, 235, 0.9)',
'rgba(255, 206, 86, 0.9)',
'rgba(75, 192, 192, 0.9)',
'rgba(153, 102, 255, 0.9)',
'rgba(255, 159, 64, 0.9)'
],
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: 5
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
Add 'responsive: false' to the chart options
options: {
responsive: false,
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}

Categories