Related
Below is my attempt to update a chart once per second with random data and dynamically repaint the chart. The function adddata() pushes random data to the data array but the chart UI is not updating and appears static. How to update the chart dynamically when new data is added ?
src:
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<div class="chart-container" style="position: absolute; height:20vh; width:40vw">
<canvas id="myChart1"></canvas>
<input onclick="adddata()" type="button" value="Add Data">
</div>
$(document).ready(function () {
var canvas1 = document.getElementById('myChart1');
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 5,
pointHitRadius: 10,
data: [65, 59, 80, 0, 56, 55, 40],
}
]
};
function adddata() {
setInterval(function () {
console.log('invoking' + Math.random() * 10)
myLineChart.data.datasets[0].data.push(Math.floor(Math.random() * 10))
myLineChart.update();
}, 1000)
}
var option = {
showLines: true
};
var myLineChart = Chart.Line(canvas1, {
data: data,
options: option
});
adddata();
});
fiddle src: https://jsfiddle.net/adrianfiddleuser/jq1pzkrs/6/
The function is called once per second, on console following is dispayed:
Right now you're adding an extra slot to the dataset (you need to have the same amount of labels as data in the dataset, so if you want to add more data - also add more labels) - try replacing a data instead, like:
$(document).ready(function () {
var canvas1 = document.getElementById('myChart1');
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 5,
pointHitRadius: 10,
data: [65, 59, 80, 0, 56, 55, 40],
}
]
};
function adddata() {
setInterval(function () {
let randomIndex = Math.floor(Math.random() * Math.floor(myLineChart.data.datasets[0].data.length));
myLineChart.data.datasets[0].data[randomIndex] = Math.floor(Math.random() * 100);
myLineChart.update();
}, 1000)
}
var myLineChart = Chart.Line(canvas1, {
data: data,
options: option
});
var option = {
showLines: true
};
adddata();
});
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<div class="chart-container" style="position: absolute; height:20vh; width:40vw">
<canvas id="myChart1"></canvas>
<input onclick="adddata()" type="button" value="Add Data">
</div>
You can read more about in the documentation: https://www.chartjs.org/docs/latest/developers/updates.html
function method() {
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
}
]
},
options: {
responsive: false,
}
});
I added a function to add a new value on the chart
function addvalue() {
myChart.data.labels.concat("August");
myChart.data.datasets[0].data.concat(55);
myChart.update();
but compiler say me "myChart is not declared" How can I draw the chart in this case?
I've just started with canvas and these charts
As Mihai has pointed out, read deeply into MDN's documentation about functions and about scope.
Your code needs to export or make the myChart variable accessible to other functions. Here is the quick and dirty fix - you need to decide what is best for your app.
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
}
]
},
options: {
responsive: false,
}
});
This is global scope (not the best), but it will allow your other function to access it:
function addvalue() {
// myChart is now globally accessible
myChart.data.labels.concat("August");
myChart.data.datasets[0].data.concat(55);
myChart.update();
}
Without knowing more context I can't specifically say to do something better (like require your chart into other code)
Scope is important and also you want to return something
function method() {
return new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
}
]
},
options: {
responsive: false,
}
});
var myChart = method();
function addvalue(myChart) {
myChart.data.labels.concat("August");
myChart.data.datasets[0].data.concat(55);
myChart.update();
return myChart;
}
i got a dynamically loaded Chart working on several browsers and also on my iPhone. But when i try to open the chart with phonegap on my iPhone the canvas is totally buggy.
Are there any known issues using Chart JS with Phonegap?
it should look like this:
but with Phonegap it looks like this:
HTML:
<div id="temp_graph" style="display:none;">
<h2 id="tmp_label"></h2>
<canvas id="myChart"></canvas>
CSS:
#temp_graph {
margin-top: 5%;
width: 90%;
background-color: #fff;
display: inline-block;
padding: 2%;
box-shadow: 0 0 10px 0 rgba(0, 0, 58, 0.05);
}
JS:
var temp_graph_div = document.getElementById('temp_graph');
var canvas = document.getElementById('myChart'),
ctx = canvas.getContext('2d'),
startingData = {
labels: [tempValues[9][3], tempValues[8][3], tempValues[7][3], tempValues[6][3], tempValues[5][3], tempValues[4][3], tempValues[3][3], tempValues[2][3], tempValues[1][3], tempValues[0][3]],
datasets: [{
label: '°C',
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(255, 205, 200,0.4)",
borderColor: "rgba(255, 205, 200,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
responsive: true,
maintainAspectRatio: true,
data: [tempValues[9][6], tempValues[8][6], tempValues[7][6], tempValues[6][6], tempValues[5][6], tempValues[4][6], tempValues[3][6], tempValues[2][6], tempValues[1][6], tempValues[0][6]]
}]
};
var myChart = new Chart(ctx, {
type: 'line',
data: startingData,
});
temp_graph_div.style.display = 'inherit';
Any ideas?
EDIT:
added a border for the canvas and opened the website via browser (safari ios)
added a border for the canvas and opened the website via phonegap
seems like the width is incorrect, but why are there different widths for the same mobile device?
i could fix the issue =)
The issue was caused by setting the div
temp_graph_div.style.display = 'inherit';
after creating the chart.
Now, my code looks like this (no big change, but big success):
var temp_graph_div = document.getElementById('temp_graph');
temp_graph_div.style.display = 'inherit';
var canvas = document.getElementById('myChart'),
ctx = canvas.getContext('2d'),
startingData = {
labels: [tempValues[9][3], tempValues[8][3], tempValues[7][3], tempValues[6][3], tempValues[5][3], tempValues[4][3], tempValues[3][3], tempValues[2][3], tempValues[1][3], tempValues[0][3]],
datasets: [{
label: '°C',
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(255, 205, 200,0.4)",
borderColor: "rgba(255, 205, 200,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
responsive: true,
maintainAspectRatio: true,
data: [tempValues[9][6], tempValues[8][6], tempValues[7][6], tempValues[6][6], tempValues[5][6], tempValues[4][6], tempValues[3][6], tempValues[2][6], tempValues[1][6], tempValues[0][6]]
}]
};
var myChart = new Chart(ctx, {
type: 'line',
data: startingData,
});
I'm using charts.js. For my current need, I managed to find a way to configure tooltips to be always visible regardless of the hover event. My problem is that the tooltip visibility does not follow the dataset behaviour. On charts.js, you can click on a dataset in order to remove it from the graph. My graph does that, but the tooltips are still there visible, floating within the graph with no dataset to represent. Is there a way to hide then with the dataset data when the label is clicked ?
Here is an example of the current state of what i said. https://jsfiddle.net/CaioSantAnna/ddejheg0/ .
HTML
<canvas id="linha"></canvas>
Javascript
Chart.plugins.register({
beforeRender: function (chart) {
if (chart.config.options.showAllTooltips) {
// create an array of tooltips
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function (dataset, i) {
chart.getDatasetMeta(i).data.forEach(function (sector, j) {
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector]
}, chart));
});
});
// turn off normal tooltips
chart.options.tooltips.enabled = false;
}
},
afterDraw: function (chart, easing) {
if (chart.config.options.showAllTooltips) {
// we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
if (!chart.allTooltipsOnce) {
if (easing !== 1)
return;
chart.allTooltipsOnce = true;
}
// turn on tooltips
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
tooltip.initialize();
tooltip.update();
// we don't actually need this since we are not animating tooltips
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
});
ctx = document.getElementById("linha");
var linha = new Chart(ctx, {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
responsive: true,
animation: true,
},
{
label: "Second dataset",
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(0,0,0,0.4)",
borderColor: "rgba(0,0,0,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(0,0,0,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(0,0,0,1)",
pointHoverBorderColor: "rgba(0,0,0,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [13, 78, 60, 75, 90, 10, 27],
spanGaps: false,
responsive: true,
animation: true,
}
]
},
options: {
tooltips: {
callbacks: {
title: function (tooltipItem, data) { return "" },
label: function (tooltipItem, data) {
var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || 'Other';
var label = data.labels[tooltipItem.index];
return value;
}
}
},showAllTooltips: true
}
});
To reproduce the problem, just click in one of the labels on the top of the graph.
Thanks in advance.
Just to close the question, I ended up changing to amcharts(https://www.amcharts.com/). It has features like the one i was trying to achieve with chart.js and is free to use under a linkware license.
Thanks again.
Well, i have the same issue that this guy: Chart.js not showing in my view , for him it solved to set a timeout but for me that's no even possible to introduce in my web, i don't want to work with timeouts.I'm working to create web-components for chart.js.There's any way to wait the chart to get render without setting a timeout?, that the waiting time is the render time
My code is:
flexygo.ui.wc.flxChart = function () {
return {
htmlItem: null,
moduleId: null,
refresh: function () {
this.init();
},
init: function () {
var ctx = this;
ctx.htmlItem.html('<canvas id="myChart2" height="400" width="800" style="width:800px;height:400px;"></canvas>');
ctx.render();
},
render: function () {
var ctx = this;
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40],
spanGaps: false,
}]
};
window.onload = function () {
var myChart = new Chart(ctx.htmlItem[0].childNodes[0], {
type: 'line',
data: data,
options: {
scales: {
xAxes: [{
display: false
}]
}
}
});
}
},
translate: function (str) {
return flexygo.localization.translate(str);
},
startLoading: function () {
this.htmlItem.parents('flx-module').find('.icon-sincronize').addClass('icon-spin txt-outstanding');
},
stopLoading: function () {
this.htmlItem.parents('flx-module').find('.icon-sincronize').removeClass('icon-spin txt-outstanding');
},
}
creating the chart we can use either htmlitem[0].childnodes[0] or document.getElementById('myChart2')
i solved it adding encapsulating the canvar into a div, so the canva resizes with my page, i changed:
from:
ctx.htmlItem.html('<canvas id="myChart2" height="400" width="800" style="width:800px;height:400px;"></canvas>');
to
ctx.htmlItem.html('<div><canvas id="myChart2" height="400" width="800" style="width:800px;height:400px;"></canvas></div>');
a now it works