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;
}
Related
So I've got a bar chart which has two different bars for supply and demand and I want it to tell me which one it is when I click on the bar. Because right now it just gives me the same index and x axis when I click on the bars. So how can I fix this problem? Here is my code :
var canvas = document.getElementById('myChart');
var data = {
labels: ["iOS", "Android", "React", "Angular", "SA", "BA", "Backbase"],
datasets: [
{
label: "supply",
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,
grouped: true,
pointHitRadius: 10,
data: [1, 2, 3, 4, 5, 6, 7],
},
{
label: "demand",
fill: false,
lineTension: 0.1,
backgroundColor: "rgba(75,29,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,
grouped: true,
pointHitRadius: 10,
data: [5, 9, 8, 1, 6, 5, 4],
}
]
};
var option = {
showLines: true,
onClick: function(evt) {
console.log(myLineChart.getElementAtEvent(evt));
alert(data.datasets[0].data[myLineChart.getElementAtEvent(evt)[0]._index]);
alert(data.labels[myLineChart.getElementAtEvent(evt)[0]._index]);
}
};
var myLineChart = Chart.Bar(canvas,{
data:data,
options:option
});
Hey guys I figured it out here is the code :
alert(data.labels[myLineChart.getElementAtEvent(evt)[0]._index])
alert(data.datasets[myLineChart.getElementAtEvent(evt)[0]._datasetIndex].label)
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
I'm using React Charts. I have a line chart and I'd like to be able to switch between 2 sets of data.
Using the tag I made a dropdown. Take a look at a live example:
https://codesandbox.io/s/mm2vnz6869
Go to the dropdown and switch to "Revenue". Notice that it switches to the other set of data as desired. But now try to switch back to "Spend". Notice it does not work.
Why is that? Can someone take a look at my logic and let me know what I'm doing wrong? Thanks.
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Line } from 'react-chartjs-2';
let lineData;
const lineDataSpend = {
labels: ['March', 'April', 'May', 'June', 'July', 'August', 'September'],
datasets: [
{
label: 'Spend - Account 1',
fill: false,
lineTension: 0.1,
backgroundColor: 'green',
borderColor: 'green',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'green',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: 'Spend - Account 2',
fill: false,
lineTension: 0.1,
backgroundColor: 'blue',
borderColor: 'blue',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'blue',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [25, 5, 8, 53, 96, 35, 20]
}
]
};
const lineDataRev = {
labels: ['March', 'April', 'May', 'June', 'July', 'August', 'September'],
datasets: [
{
label: 'Revenue - Account 1',
fill: false,
lineTension: 0.1,
backgroundColor: 'red',
borderColor: 'red',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'red',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [27, 9, 37, 31, 102, 42, 19]
},
{
label: 'Revenue - Account 2',
fill: false,
lineTension: 0.1,
backgroundColor: 'yellow',
borderColor: 'yellow',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'yellow',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [1, 29, 4, 112, 26, 49, 81]
}
]
};
lineData = lineDataSpend; //init the graph data to 'Spend'
class App extends Component {
constructor(props) {
super(props);
this.changeMetric = this.changeMetric.bind(this);
this.state = {
selectedMetric: 'Spend'
};
}
changeMetric(event) {
this.setState({
selectedMetric: event.target.value
});
switch (event.target.value) {
case 'Spend':
lineData = lineDataSpend;
break;
case 'Revenue':
lineData = lineDataRev;
break;
default:
}
}
render() {
const lineOptions = {
title: {
display: true,
text: 'Account 1 vs Account 2'
},
tooltips: {
enabled: true,
callbacks: {
label: function (value, data) {
console.log('data', data)
const currentLabel = data.datasets[value.datasetIndex].label;
return currentLabel + ': ' + '$' + value.yLabel;
}
}
},
legend: {
display: true
},
maintainAspectRatio: true,
scales: {
yAxes: [{
ticks: {
callback: function (value) {
return '$' + parseFloat(value.toFixed(2));
}
},
stacked: false,
gridLines: {
display: true,
color: "rgba(255,99,132,0.2)"
}
}],
xAxes: [{
gridLines: {
display: false
}
}]
}
};
return (
<div>
<select onChange={this.changeMetric} value={this.state.selectedMetric}>
<option value="Spend">Spend</option>
<option value="Revenue">Revenue</option>
</select>
<div className="row">
<div className="col-xl-10">
<div className="card">
<div className="card-header">
<i className="fa fa-align-justify" />
</div>
<div className="card-block">
<Line data={lineData} options={lineOptions} />
</div>
</div>
</div>
</div>
</div>
)
}
}
render(<App />, document.body);
In addition to this, Is there a way we could show both graphs at once by using checkbox's? For example, if there are two checkbox's spent, revenue and few other options.If we check spent shows spent data on the graph, if we check both boxes or more it shows all those graphs as such. Please help.
Your lineData initialisation to lineDataSpend is causing the issue. If you directly assign a default object to lineData instead of making it hold the object of lineDataSpend, your problem gets solved.
So, if you change line 103,
lineData = lineDataSpend; //init the graph data to 'Spend'
to
lineData = {
labels: ['March', 'April', 'May', 'June', 'July', 'August', 'September'],
datasets: [
{
label: 'Spend - Account 1',
fill: false,
lineTension: 0.1,
backgroundColor: 'green',
borderColor: 'green',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'green',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: 'Spend - Account 2',
fill: false,
lineTension: 0.1,
backgroundColor: 'blue',
borderColor: 'blue',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'blue',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [25, 5, 8, 53, 96, 35, 20]
}
]
}
your problem will get solved. You can test the fix here - https://codesandbox.io/s/3rko469pkm
But even I am not clear as to why your initial assignment is causing problem because the assignment looks perfectly fine. Will have to dig deeper to know the reason behind this issue.
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