Related
I've been trying to add a click event to each column in a bar chart using Chart.js. What I'm trying to figure out is how to make a click event on each column execute the code I want.
The goal for this is when a user clicks on a particular bar of the chart, it executes a php form submit that takes them to another page on the website.
The bar chart data is populated from an SQL database via php when the user goes to the page.
Here's an example of the code I have so far ...
<canvas id="briskChart" style="margin:auto;display:block;background-color:white;border-style:solid;border-width:1px;padding:10px;"></canvas>
<script>
var red = <?=json_encode($count1[0]);?>;
var yellow = <?=json_encode($count2[0]);?>;
var green = <?=json_encode($count3[0]);?>;
var blue = <?=json_encode($count4[0]);?>;
var grey = <?=json_encode($count5[0]);?>;
var dept = <?=json_encode($row['dept']);?>;
var c1 = document.getElementById('briskChart')
var ctx = c1.getContext("2d");
var briskChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Yellow', 'Green', 'Watch', 'Retired'],
datasets: [{
data: [red, yellow, green, blue, grey],
backgroundColor: [
'rgba(255, 0, 0, 0.4)',
'rgba(255, 216, 0, 0.4)',
'rgba(0, 255, 0, 0.4)',
'rgba(0, 0, 255, 0.4)',
'rgba(160, 160, 160, 0.4)'
],
borderColor: [
'rgba(255, 0, 0, 1)',
'rgba(255, 216, 0, 1)',
'rgba(0, 255, 0, 1)',
'rgba(0, 0, 255, 1)',
'rgba(160, 160, 160, 1)'
],
borderWidth: 1
}]
},
options: {
onClick: event => {
document.bred.submit();
},
title: {
display: true,
fontSize: 24,
text: dept + ' Dept Risk Summary',
fontColor: '#000000'
},
legend: {
display: false,
},
scales: {
xAxes: [{
display: true,
gridLines: {color: '#000000'},
ticks: {
fontColor: "black",
fontSize: 16
}
}],
yAxes: [{
display: true,
gridLines: {color: '#000000'},
ticks: {
beginAtZero: true,
fontColor: "black",
fontSize: 16,
stepSize: 1
}
}],
}
}
});
</script>
Here is the html:
<form action='../php/bred.php' method='POST' name='bred'>
</form>
The documentation for Chart.js is very limited regarding click events. For each data series, when the column is clicked on, I want to run a corresponding document.[form name].submit to take the user to that new page.
If anybody has any experience doing this with Chart.js and could point me in the right direction, I'd be eternally grateful.
You can create a click handler that retrieves the x and y values from the chart. Then, using that data, you could send a GET or POST request to your PHP script.
Example for getting the values from the bar chart (the key here is to look at the onClick function):
var red, yellow, green, blue, grey, dept = "";
var c1 = document.getElementById('briskChart')
var ctx = c1.getContext("2d");
var briskChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Yellow', 'Green', 'Watch', 'Retired'],
datasets: [{
data: [1, 2, 3, 4, 5],
backgroundColor: [
'rgba(255, 0, 0, 0.4)',
'rgba(255, 216, 0, 0.4)',
'rgba(0, 255, 0, 0.4)',
'rgba(0, 0, 255, 0.4)',
'rgba(160, 160, 160, 0.4)'
],
borderColor: [
'rgba(255, 0, 0, 1)',
'rgba(255, 216, 0, 1)',
'rgba(0, 255, 0, 1)',
'rgba(0, 0, 255, 1)',
'rgba(160, 160, 160, 1)'
],
borderWidth: 1
}]
},
options: {
onClick: function(c, i) {
element = i[0]; // the chart element you clicked on
var xValue = this.data.labels[element._index]; // the x-value of the bar
var yValue = this.data.datasets[0].data[element._index]; // the y-value of the bar
console.log(xValue);
console.log(yValue);
// then, here, you could send a GET/POST request to your PHP function
},
title: {
display: true,
fontSize: 24,
text: dept + ' Dept Risk Summary',
fontColor: '#000000'
},
legend: {
display: false,
},
scales: {
xAxes: [{
display: true,
gridLines: {
color: '#000000'
},
ticks: {
fontColor: "black",
fontSize: 16
}
}],
yAxes: [{
display: true,
gridLines: {
color: '#000000'
},
ticks: {
beginAtZero: true,
fontColor: "black",
fontSize: 16,
stepSize: 1
}
}],
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<canvas id="briskChart">
</canvas>
I have to display a line chart with two different datasets in one single chart. After execution of query I got the plan_plan and actual_plan of the following form.
plan_plan = 0: {week: "46", planned_del: "20"}
1: {week: "53", planned_del: "94"}
actual_plan = 0: {week: "8", actual_del: "1"}
javascript part:
function show_Graph()
{
{
var plandata = <?php echo json_encode($plan_plan); ?>;
var actualdata = <?php echo json_encode($actual_plan); ?>;
console.log(plandata);
var labels = [];
var plandel = [];
var actualdel = [];
for (var i in plandata) {
labels.push(plandata[i].week);
plandel.push(plandata[i]);
}
for (var j in actualdata) {
labels.push(actualdata[j].week);
actualdel.push(actualdata[j]);
}
var chartdata = {
labels: labels,
datasets: [
{
label: "Planned Deliverables",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
pointHoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: plandel
},
{
label: "Actual Deliverables",
fill: false,
backgroundColor: "rgba(0, 255, 0, 0.75)",
borderColor: "rgba(0, 255, 0, 1)",
pointHoverBackgroundColor: "rgba(0, 255, 0, 1)",
pointHoverBorderColor: "rgba(0, 255, 0, 1)",
data: actualdel
}
]
};
var graphTarget = $("#scurve_chart");
var barGraph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options: {
elements: {
point:{
radius: 1,
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
barValueSpacing: 2,
barPercentage: 0.2
}]
}
}
});
}}
I want to get the week in x axis and then planned_del and actual_del data in y axis which can be shown as line chart. And also should show a single point entry even when there is no data points to be connected.
One way for achieving this, would be to defined data.labels as an array of numbers from 0 to 53.
labels: [0, 1, 2, ... 53]
The data inside the two datasets would then only contain the definitions of individual points.
data: [{ x: 46, y: 20 }, { x: 53, y: 94 }] // plandata
...
data: [{ x: 8, y: 1}] // actualdata
Here's the JavaScript part that illustrates how the desired result can be obtained.
var plandata = [{ week: "46", planned_del: "20" }, { week: "53", planned_del: "94" }];
var actualdata = [{ week: "8", actual_del: "1" }];
new Chart("scurve_chart", {
type: 'line',
data: {
labels: Array.from(new Array(54), (x, i) => i),
datasets: [{
label: "Planned Deliverables",
fill: false,
borderColor: "rgba(255, 0, 0, 1)",
pointHoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: plandata.map(o => ({ x: Number(o.week), y: Number(o.planned_del)}))
},
{
label: "Actual Deliverables",
fill: false,
backgroundColor: "rgba(0, 255, 0, 0.75)",
borderColor: "rgba(0, 255, 0, 1)",
pointHoverBackgroundColor: "rgba(0, 255, 0, 1)",
pointHoverBorderColor: "rgba(0, 255, 0, 1)",
data: actualdata.map(o => ({x: Number(o.week), y: Number(o.actual_del)}))
}
]
},
options: {
tooltips: {
callbacks: {
title: (tooltipItem, data) => "Week " + data.datasets[tooltipItem[0].datasetIndex].data[tooltipItem[0].index].x
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
ticks: {
min: 0,
max: 53,
stepSize: 1
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<canvas id="scurve_chart" height="90"></canvas>
Here is an example of one run of my chart:
Chart configuration:
At the moment I just set a maximum tick value, i.e. max: 100000000. I figure I need to pass some function that adjusts the maximum value whenever the largest exceeds the largest value of the y axis. How can this be done?
_chart.chart_3.config = {
type: 'line',
data: {
labels: ['Harvest 1', 'Harvest 2', 'Harvest 3', 'Harvest 4','Harvest 5'],
datasets: [{
lineTension: 0,
label: 'Bill',
data: [],
fill: false,
fillColor : "rgba(0, 0, 0, 1)",
strokeColor : "rgba(0, 0, 0, 1)",
backgroundColor: "rgb(54, 162, 235)",
borderColor: "rgb(54, 162, 235)",
},
{
lineTension: 0,
label: 'Ann',
data: [],
fill: false,
fillColor : "rgba(0, 0, 0, 1)",
strokeColor : "rgba(0, 0, 0, 1)",
backgroundColor: "rgb(255, 99, 132)",
borderColor: "rgb(255, 99, 132)",
},
{
lineTension: 0,
label: 'Bill (Sharing)',
data: [],
fill: false,
fillColor : "rgba(0, 0, 0, 1)",
strokeColor : "rgba(0, 0, 0, 1)",
backgroundColor: "rgb(4, 0, 255)",
borderColor: "rgb(4, 0, 255)",
},
{
lineTension: 0,
label: 'Ann (Sharing)',
data: [],
fill: false,
fillColor : "rgba(0, 0, 0, 1)",
strokeColor : "rgba(0, 0, 0, 1)",
backgroundColor: "rgb(255, 0, 0)",
borderColor: "rgb(255, 0, 0)",
},
{
lineTension: 0,
label: 'Pool',
data: [],
fill: false,
fillColor : "rgba(0, 0, 0, 1)",
strokeColor : "rgba(0, 0, 0, 1)",
backgroundColor: "rgb(128,36,171)",
borderColor: "rgb(128,36,171)",
}]
},
options: {
responsive: true,
title: {
display: true,
text: ''
},
tooltips: {
enabled: false,
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'KG',
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: newMax(value), //maximum tick
callback: function (value, index, values) {
return Number(value.toString()); //pass tick values as a string into Number function
}
}
}]
}
}
};
New max function:
newMax = function(values) {
max = Math.max(values)
max = max * 1.2
return Number(max.toString())
}
I'm not sure what your data looks like, but I'm assuming it's an array of values with numbers, all you'd need to do is find the max number than add a little buffer on the end to keep the graph looking pretty, so the max number it goes to, then add a little on the end.
function getMax(arr) {
const max = Math.max(...arr).toString();
const newMax = 1 + "0".repeat(max.length);
return newMax
}
max: getMax(values)
I'm using http://www.chartjs.org/ library for charts where I try to display 6 different data points on Y axis.
It's a bit mess when everything is displayed at the same time, but I do not want to split it into multiple charts as all these data correlate.
I wonder if it's possible to set which data should be hidden when the chart loads and then I could show the remaining ones myself.
Also is it possible to save these settings somehow? Let's say I want to display only 3 types of data and after I reload the page it would remember my preference.
EDIT: Here is the current code if it helps..
<canvas id="statsByDayChart" width="400" height="300"></canvas>
<script>
var ctx = document.getElementById('statsByDayChart').getContext('2d');
var profit = {
label: "Profit",
data: {!! json_encode($profit) !!},
borderColor: 'rgba(73, 189, 138, 1)',
borderWidth: 3,
backgroundColor: 'rgba(219, 242, 232, 0)',
pointBorderWidth: 4,
pointBackgroundColor: '#128ffb',
yAxisID: 'y-axis-profit',
type: 'line'
};
var cost = {
label: "Cost",
data: {!! json_encode($cost) !!},
borderColor: 'rgba(255, 0, 0, 1)',
borderWidth: 2,
backgroundColor: 'rgba(255, 0, 0, 0)',
pointBorderWidth: 4,
pointBackgroundColor: '#128ffb',
yAxisID: 'y-axis-cost',
type: 'line'
};
var ctr = {
label: "CTR",
data: {!! json_encode($ctr) !!},
borderColor: 'rgba(255, 126, 0, 1)',
borderWidth: 3,
backgroundColor: 'rgba(255, 126, 0, 0)',
pointBorderWidth: 4,
pointBackgroundColor: '#128ffb',
yAxisID: 'y-axis-ctr',
type: 'line'
};
var holds = {
label: "Holds",
data: {!! json_encode($holds) !!},
borderColor: 'rgb(175, 26, 245, 1)',
backgroundColor: 'rgb(175, 26, 245, 1)',
borderWidth: 4,
pointBorderWidth: 4,
pointBackgroundColor: '#128ffb',
yAxisID: 'y-axis-holds',
type: 'bar',
fill: true
};
var conversions = {
label: "Conversions",
data: {!! json_encode($conversions) !!},
borderColor: 'rgb(54, 162, 235, 1)',
backgroundColor: 'rgb(54, 162, 235, 1)',
borderWidth: 5,
pointBorderWidth: 4,
pointBackgroundColor: '#128ffb',
yAxisID: 'y-axis-conversions',
type: 'bar',
fill: true
};
var impressions = {
label: "Impressions",
data: {!! json_encode($displays) !!},
borderColor: 'rgba(254, 206, 96, 1)',
backgroundColor: 'rgba(255, 231, 175, 0.8)',
borderWidth: 6,
pointBorderWidth: 4,
borderDash: [20, 6],
pointBackgroundColor: '#128ffb',
yAxisID: 'y-axis-impressions',
type: 'line',
fill: true
};
var chartData = {
labels: {!! json_encode($days) !!},
datasets: [profit, cost, ctr, holds, conversions, impressions]
};
var lineChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
legend: {display: true},
responsive: true,
maintainAspectRatio: false,
elements: { line: { tension: 0.05 } },
scales: {
xAxes: [{ gridLines: { display: true, offsetGridLines: false }, barPercentage: 1, categoryPercentage: 0.4 }],
yAxes: [
{
id: 'y-axis-profit',
type: 'linear',
gridLines: { display: true },
ticks: { beginAtZero: true, min: {{ $profit->min() }}, max: {{ $profit->max() }} },
display: true
},
{
id: 'y-axis-cost',
type: 'linear',
gridLines: { display: false },
ticks: { beginAtZero: true, min: {{ $cost->min() }}, max: {{ $cost->max() }} },
display: false
},
{
id: 'y-axis-ctr',
type: 'linear',
gridLines: { display: false },
ticks: { beginAtZero: true, min: {{ $ctr->min() }}, max: {{ $ctr->max() }} },
display: false
},
{
id: 'y-axis-holds',
type: 'linear',
gridLines: { display: false },
ticks: { beginAtZero: true, min: {{ $holds->min() }}, max: {{ $holds->max() }} },
display: false,
},
{
id: 'y-axis-conversions',
type: 'linear',
gridLines: { display: false },
ticks: { beginAtZero: true, min: {{ $conversions->min() }}, max: {{ $conversions->max() }} },
display: false,
},
{
id: 'y-axis-impressions',
type: 'linear',
gridLines: { display: false },
ticks: { beginAtZero: true, min: {{ $displays->min() }}, max: {{ $displays->max() }} },
display: false
}
]
},
tooltips: { mode: 'index', intersect: false },
hover: { mode: 'nearest', intersect: true },
}
});
</script>
I'm using chart.js on a project, a canvas on the html.
However, the data i'm inputting there doesn't go along with the label.
The data bars are not following the axes properly. Is there a way to add a padding, to the bar? Or something similar?
I've tried many ways, but can't get it right.
Here is my config:
$(window).on("load", function(){
//Get the context of the Chart canvas element we want to select
var ctx = $("#bar-multi-axis");
// Chart Options
var chartOptions = {
responsive: true,
maintainAspectRatio: false,
responsiveAnimationDuration:500,
hoverMode: 'label',
stacked: false,
title:{
display:false,
text:"Chart.js Bar Chart - Multi Axis"
},
scales: {
xAxes: [{
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "bottom",
id: "x-axis-1",
gridLines: {
color: "#f3f3f3",
drawTicks: true,
},
scaleLabel: {
display: true,
}
}, {
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: false,
position: "bottom",
id: "x-axis-2",
gridLines: {
drawOnChartArea: false
}
}],
yAxes: [{
display: true,
gridLines: {
color: "#f3f3f3",
drawTicks: true,
},
scaleLabel: {
display: false,
}
}]
}
};
// Chart Data
var chartData = {
labels: ["Ações", "Opções", "Termo", "BM&F", "Garantias","Tesouro Direto","Financeiro","BTC","Renda Fixa","Clubes e fundos"],
datasets: [{
label: "Ações",
data: [45],
backgroundColor: "#5175E0",
hoverBackgroundColor: "rgba(81,117,224,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
}, {
label: "Opções",
data: [28],
backgroundColor: "#16D39A",
hoverBackgroundColor: "rgba(22,211,154,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "Termo",
data: [-40],
backgroundColor: "#F98E76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "BM&F",
data: [25],
backgroundColor: "#F00E76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "Garantias",
data: [-16],
backgroundColor: "#E12E76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "Tesouro Direto",
data: [10],
backgroundColor: "#E98A76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "Financeiro",
data: [-12],
backgroundColor: "#F98A76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "BTC",
data: [50],
backgroundColor: "#F18E76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "Renda Fixa",
data: [24],
backgroundColor: "#D98E76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
},
{
label: "Clubes e fundos",
data: [-24],
backgroundColor: "#A98E76",
hoverBackgroundColor: "rgba(249,142,118,.8)",
borderColor: "transparent",
xAxisID: "x-axis-1",
}]
};
var config = {
type: 'horizontalBar',
// Chart Options
options : chartOptions,
data : chartData
};
// Create the chart
var lineChart = new Chart(ctx, config);
});
I suggest to use only one dataset and define specific color for each bar using an array asbackgroundColor property:
datasets: [{
label: "my set",
data: [45, 28, -40, 25, -16, 10, -12, 50, 24, -24],
backgroundColor: ["rgba(255, 99, 132, 0.6)", "rgba(255, 159, 64, 0.6)", "rgba(255, 205, 86, 0.6)", "rgba(75, 192, 192, 0.6)", "rgba(54, 162, 235, 0.6)", "rgba(153, 102, 255, 0.6)", "rgba(201, 203, 207, 0.6)", "rgba(155, 99, 132, 0.6)","rgba(255, 99, 32, 0.6)"],
borderColor: "transparent",
xAxisID: "x-axis-1",
}]
Check my fiddle: https://jsfiddle.net/beaver71/2hp160zh/
// Chart Options
var chartOptions = {
responsive: true,
maintainAspectRatio: false,
responsiveAnimationDuration:500,
hoverMode: 'label',
stacked: false,
legend: {display:false,},
title:{
display:false,
text:"Chart.js Bar Chart - Multi Axis"
},
scales: {
xAxes: [{
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "bottom",
id: "x-axis-1",
gridLines: {
color: "#f3f3f3",
drawTicks: true,
},
scaleLabel: {
display: true,
}
}, {
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: false,
position: "bottom",
id: "x-axis-2",
gridLines: {
drawOnChartArea: false
}
}],
yAxes: [{
display: true,
type: 'category',
gridLines: {
color: "#f3f3f3",
drawTicks: true,
},
scaleLabel: {
display: false,
}
}]
}
};
// Chart Data
var chartData = {
labels: ["Ações", "Opções", "Termo", "BM&F", "Garantias","Tesouro Direto","Financeiro","BTC","Renda Fixa","Clubes e fundos"],
datasets: [{
label: "my set",
data: [45, 28, -40, 25, -16, 10, -12, 50, 24, -24],
backgroundColor: ["rgba(255, 99, 132, 0.6)", "rgba(255, 159, 64, 0.6)", "rgba(255, 205, 86, 0.6)", "rgba(75, 192, 192, 0.6)", "rgba(54, 162, 235, 0.6)", "rgba(153, 102, 255, 0.6)", "rgba(201, 203, 207, 0.6)", "rgba(155, 99, 132, 0.6)","rgba(255, 99, 32, 0.6)"],
borderColor: "transparent",
xAxisID: "x-axis-1",
}]
};
var config = {
type: 'horizontalBar',
options : chartOptions,
data : chartData
};
var lineChart = new Chart('myChart', config);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<canvas id="myChart" width="400" height="600"></canvas>