Chart.js - Tooltips overlapped by bar values - chart.js

In bar charts, label above bars overlaps tooltip. Please see screenshots below.
Bar chart - original
Bar chart - tooltip problem
Please see my code below.
<!doctype html>
<html>
<head>
<title>Single Bar Chart</title>
<script src="Chart.min.js"></script>
<style>
canvas {
border:1px solid #367ee9;
}
#container{
width: 950px;
}
</style>
</head>
<body>
<div id="container">
<canvas id="canvas"></canvas>
</div>
<script>
var barChartData = {
labels: ["Jul 19", "Aug 19", "Sep 19", "Oct 19", "Nov 19", "Dec 19", "Jan 20", "Feb 20", "Mar 20", "Apr 20", "May 20", "Jun 20"],
datasets: [{
//label: 'Jan 20',
backgroundColor: '#367ee9',
borderColor: '#367ee9',
borderWidth: 1,
data: [33111, 27510, 27377, 14947, 4312, 7279, 70988, 2903, 29575, 65, 9861, 3416],
data_action: ["bar1_action", "bar2_action", "bar3_action", "bar4_action", "bar5_action", "bar6_action", "bar7_action", "bar8_action", "bar9_action", "bar10_action", "bar11_action", "bar12_action"],
data_alt: ["Click here to see results of bar1_alt", "bar2_alt", "bar3_alt", "bar4_alt", "bar5_alt", "bar6_alt", "bar7_alt", "bar8_alt", "bar9_alt", "bar10_alt", "bar11_alt", "bar12_alt"],
}]
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
responsive: true,
onHover: (event, chartElement) => {
event.target.style.cursor = chartElement[0] ? 'pointer' : 'default';
},
hover: {
animationDuration: 0,
},
animation: {
duration: 1000,
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';
//ctx.canvas.style.zIndex = 5;
this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
var val = dataset.data[index];
var data = "$" + val.toLocaleString();
if(val > -1){
ctx.fillText(data, bar._model.x, bar._model.y - 5);
}
else{
ctx.fillText(data, bar._model.x, bar._model.y + 14);
}
});
});
}
},
onClick:function(evt) {
var firstPoint = this.getElementAtEvent(evt)[0];
if (firstPoint) {
var value = this.data.datasets[firstPoint._datasetIndex].data_action[firstPoint._index];
alert(value);
}
},
legend: {
display: false,
position: 'top',
onHover:function(){
event.target.style.cursor = 'pointer';
},
},
title: {
display: true,
text: 'Total Benefits Exceeded ($231,345) (Claim Date)',
fontColor: '#000',
fontSize: '15',
},
tooltips: {
yAlign:'top',
displayColors: false, // hide color box
yPadding: 10,
xPadding: 10,
backgroundColor: '#fff',
borderColor: '#000',
borderWidth: 1,
bodyFontFamily: 'tahoma,Verdana,Arial, Helvetica, sans-serif',
bodyFontSize: 13,
bodyFontColor:'#000',
callbacks: {
title: function(tooltipItem, data) {
return; // hide title
},
label: function(tooltipItem, data) {
barCount = tooltipItem.index;
barIndex = tooltipItem.datasetIndex;
var label = data.datasets[barIndex].data_alt[barCount];
return label;
},
}
},
scales: {
yAxes: [{
display: false,
scaleLabel: {
display: true,
labelString: 'Denied Charges ($)',
fontColor: '#000',
fontSize: '15',
fontStyle: 'bold',
},
ticks: {
callback: function(value, index, values) {
return '$' + value.toLocaleString();
}
},
}]
}
}
});
};
</script>
</body>
</html>
Is there any way to avoid this?
I tried to find details about setting z-index in above code. But, I haven't got much help.
Other than this, the graphs work great.
Thanks,
Sandeep

At the begin of the animation.onComplete callback function, you should add the following lines:
ctx.save();
ctx.globalCompositeOperation='destination-over';
And at the end of animation.onComplete, you need to invoke ctx.restore().
For further details about ctx.globalCompositeOperation='destination-over', have a look at this answer.
Please take a look at your amended code and see how it works.
var barChartData = {
labels: ["Jul 19", "Aug 19", "Sep 19", "Oct 19", "Nov 19", "Dec 19", "Jan 20", "Feb 20", "Mar 20", "Apr 20", "May 20", "Jun 20"],
datasets: [{
//label: 'Jan 20',
backgroundColor: '#367ee9',
borderColor: '#367ee9',
borderWidth: 1,
data: [33111, 27510, 27377, 14947, 4312, 7279, 70988, 2903, 29575, 65, 9861, 3416],
data_action: ["bar1_action", "bar2_action", "bar3_action", "bar4_action", "bar5_action", "bar6_action", "bar7_action", "bar8_action", "bar9_action", "bar10_action", "bar11_action", "bar12_action"],
data_alt: ["Click here to see results of bar1_alt", "bar2_alt", "bar3_alt", "bar4_alt", "bar5_alt", "bar6_alt", "bar7_alt", "bar8_alt", "bar9_alt", "bar10_alt", "bar11_alt", "bar12_alt"],
}]
};
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
responsive: true,
onHover: (event, chartElement) => {
event.target.style.cursor = chartElement[0] ? 'pointer' : 'default';
},
hover: {
animationDuration: 0,
},
animation: {
duration: 1000,
onComplete: function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
//ctx.canvas.style.zIndex = 5;
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
var val = dataset.data[index];
var data = "$" + val.toLocaleString();
if (val > -1) {
ctx.fillText(data, bar._model.x, bar._model.y - 5);
} else {
ctx.fillText(data, bar._model.x, bar._model.y + 14);
}
});
});
ctx.restore();
}
},
onClick: function(evt) {
var firstPoint = this.getElementAtEvent(evt)[0];
if (firstPoint) {
var value = this.data.datasets[firstPoint._datasetIndex].data_action[firstPoint._index];
alert(value);
}
},
legend: {
display: false,
position: 'top',
onHover: function() {
event.target.style.cursor = 'pointer';
},
},
title: {
display: true,
text: 'Total Benefits Exceeded ($231,345) (Claim Date)',
fontColor: '#000',
fontSize: '15',
},
tooltips: {
yAlign: 'top',
displayColors: false, // hide color box
yPadding: 10,
xPadding: 10,
backgroundColor: '#fff',
borderColor: '#000',
borderWidth: 1,
bodyFontFamily: 'tahoma,Verdana,Arial, Helvetica, sans-serif',
bodyFontSize: 13,
bodyFontColor: '#000',
callbacks: {
title: function(tooltipItem, data) {
return; // hide title
},
label: function(tooltipItem, data) {
barCount = tooltipItem.index;
barIndex = tooltipItem.datasetIndex;
var label = data.datasets[barIndex].data_alt[barCount];
return label;
},
}
},
scales: {
yAxes: [{
display: false,
scaleLabel: {
display: true,
labelString: 'Denied Charges ($)',
fontColor: '#000',
fontSize: '15',
fontStyle: 'bold',
},
ticks: {
callback: function(value, index, values) {
return '$' + value.toLocaleString();
}
},
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<div id="container">
<canvas id="canvas"></canvas>
</div>

Related

Tooltip on each data point in Chartjs

Here is my code for putting different tooltip on each data point. I want to put different month on each point, but all the months get printed together. How do I separate them out?
function trendsChart(labels1, datasets1, chartId) {
var ctx =
document.getElementById(chartId).getContext('2d');
var MONTHS = ["January", "February", "March", "April", "May", "June"];
console.log(datasets1)
var data = {
labels: labels1,
datasets: datasets1,
};
// Tooltip
const titleTooltip = (tooltipItems) => {
let sum = 77;
MONTHS.forEach(function(tooltipItem) {
sum = tooltipItem;
})
return sum;
}
var randomScalingFactor = function() {
return (Math.random() > 0.5 ? 1.0 : 1.0) * Math.round(Math.random() * 100);
};
var line1 = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
myChart = new Chart(ctx, {
type: 'line',
data: data,
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
x: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
title: {
display: true,
text: 'Week Of'
}
},
y: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
stacked: false,
title: {
display: true,
text: 'Count'
}
}
},
plugins: {
tooltip: {
//yAlign: 'bottom',
callbacks: {
title: titleTooltip,
}
}
}
}
});
return myChart;
}
Inside titleTooltip in the pasted code, you replace sum with the last entry from MONTHS. The tooltip from the image however suggests that in the real code, you create an array with 77 and all entries from MONTHS, then you probably return 'Sum: ' + sum, which results in the string you can see in the tooltip.
In order to see all the months on a separate line, you could change your code as follows and return sum as an array:
const titleTooltip = ctx => {
let sum = ['Sum: 77'];
MONTHS.forEach(month => {
sum.push(month);
});
return sum;
}
The resulting tooltip still doesn't make much sense but you'll see all months on a different line. Therefore, you to extend the function titleTooltip in order to obtain the desired result.
Please take a loo at your amended code and see how it works.
function trendsChart(labels1, datasets1, chartId) {
var MONTHS = ["January", "February", "March", "April", "May", "June"];
var data = {
labels: labels1,
datasets: datasets1,
};
// Tooltip
const titleTooltip = ctx => {
let sum = ['Sum: 77'];
MONTHS.forEach(month => {
sum.push(month);
});
return sum;
}
var randomScalingFactor = function() {
return (Math.random() > 0.5 ? 1.0 : 1.0) * Math.round(Math.random() * 100);
};
var line1 = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
myChart = new Chart(chartId, {
type: 'line',
data: data,
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
x: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
title: {
display: true,
text: 'Week Of'
}
},
y: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
stacked: false,
title: {
display: true,
text: 'Count'
}
}
},
plugins: {
tooltip: {
//yAlign: 'bottom',
callbacks: {
title: titleTooltip,
label: ctx => ctx.label + ': ' + ctx.parsed.y
}
}
}
}
});
return myChart;
}
trendsChart(['created', 'tested', 'reviewed', 'approved'], [{ data: [1, 5, 3, 2]}], 'myChart');
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
<canvas id="myChart"></canvas>

How can I show chartjs datalabels only last bar?

I need to show the last bar value only. like this image:
I try this code but it shows all values.
var dataX = {
labels: [['Personne', 'seule'], ['Couple sans', 'enfant'], ['Couple avec', 'enfant(s)'], ['Famille', 'monoparentale'], 'Autres'],
datasets: [{
label: 'Data 1',
data: [33,28,25,8,2.5],
backgroundColor: '#00BBF1',
borderWidth: 0
},
{
label: 'Data 2',
data: [29,30,30,8,2],
backgroundColor: '#3CC6F4',
borderWidth: 0
},
{
label: 'Data 3',
data: [41,22,22,11,3],
backgroundColor: '#92D9F8',
borderWidth: 0
}]
};
var optionsX = {
tooltips: {
enabled: false
},
responsive: true,
maintainAspectRatio: false,
legend: false,
scales: {
xAxes: [{
gridLines : {
color: "#fff"
},
}],
yAxes: [{
gridLines : {
display : false
},
ticks: {
min: 0,
max: 50,
stepSize: 10,
callback: function(value) {
return value + "%"
},
}
}]
},
plugins: {
datalabels: {
color: '#59595B',
font: {
weight: 'bold',
size: 14,
},
align: 'end',
anchor: 'end',
formatter: function(value, context) {
return value +'%';
}
}
},
};
var ctx = document.getElementById('chart-one');
var myChart = new Chart(ctx, {
type: 'bar',
data: dataX,
options: optionsX
});
You can change the plugins.datalabels.formatter function as follows:
plugins: {
...
datalabels: {
formatter: (value, context) => context.datasetIndex == 2 ? value + '%' : ''
}
}
Please take a look at your amended code below and see how it works.
var dataX = {
labels: [
['Personne', 'seule'],
['Couple sans', 'enfant'],
['Couple avec', 'enfant(s)'],
['Famille', 'monoparentale'], 'Autres'
],
datasets: [{
label: 'Data 1',
data: [33, 28, 25, 8, 2.5],
backgroundColor: '#00BBF1',
borderWidth: 0
},
{
label: 'Data 2',
data: [29, 30, 30, 8, 2],
backgroundColor: '#3CC6F4',
borderWidth: 0
},
{
label: 'Data 3',
data: [41, 22, 22, 11, 3],
backgroundColor: '#92D9F8',
borderWidth: 0
}
]
};
var optionsX = {
tooltips: {
enabled: false
},
responsive: true,
maintainAspectRatio: false,
legend: false,
scales: {
xAxes: [{
gridLines: {
color: "#fff"
},
}],
yAxes: [{
gridLines: {
display: false
},
ticks: {
min: 0,
max: 50,
stepSize: 10,
callback: function(value) {
return value + "%"
},
}
}]
},
plugins: {
datalabels: {
color: '#59595B',
font: {
weight: 'bold',
size: 14,
},
align: 'end',
anchor: 'end',
formatter: (value, context) => context.datasetIndex == 2 ? value + '%' : ''
}
},
};
var ctx = document.getElementById('chart-one');
var myChart = new Chart(ctx, {
type: 'bar',
data: dataX,
options: optionsX
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<canvas id="chart-one"></canvas>

ChartJS Stacked Bar Chart: Showing value in opposite directions [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I want to generate a stacked bar chart like this. How can I achieve this? Any solution will be highly appreciated.
After some research and study, finally I got a way out regarding my problem I have posted here.
public static drawDashboard2Chart(data: Dashboard2Data[], canvas: ElementRef) {
const planProfit = data.map(dataUnit => dataUnit.p_profit);
const planExpenses = data.map(dataUnit => dataUnit.p_expenses);
const planSalary = data.map(dataUnit => dataUnit.p_salary);
const factProfit = data.map(dataUnit => dataUnit.f_profit);
const factExpenses = data.map(dataUnit => dataUnit.f_expenses);
const factSalary = data.map(dataUnit => dataUnit.f_salary);
const ctx = canvas.nativeElement.getContext('2d');
const dataArray = [
{
label: 'REVENUES PLAN',
backgroundColor: '#d14035',
hoverBackgroundColor: '#d14035',
stack: '0',
data: planProfit,
datalabels: {
color: '#d14035',
}
},
{
label: 'SALARY PLAN',
backgroundColor: '#72598e',
hoverBackgroundColor: '#72598e',
stack: '1',
data: planSalary,
datalabels: {
color: '#72598e',
}
},
{
label: 'EXPENSES PLAN',
backgroundColor: '#a9bb30',
hoverBackgroundColor: '#a9bb30',
stack: '1',
data: planExpenses,
datalabels: {
color: '#a9bb30',
}
},
{
label: 'ACTUAL REVENUES',
backgroundColor: '#05a6a6',
hoverBackgroundColor: '#05a6a6',
stack: '2',
data: factProfit,
datalabels: {
color: '#05a6a6',
}
},
{
label: 'ACTUAL SALARY',
backgroundColor: '#c2718c',
hoverBackgroundColor: '#c2718c',
stack: '3',
data: factSalary,
datalabels: {
color: '#c2718c',
}
},
{
label: 'ACTUAL EXPENSES',
backgroundColor: '#eb8a3c',
hoverBackgroundColor: '#eb8a3c',
stack: '3',
data: factExpenses,
datalabels: {
color: '#eb8a3c',
}
}
]
const options = {
responsive: true,
maintainAspectRatio: false,
hover: {
animationDuration: 0
},
plugins: {
datalabels: {
display: true,
align: 'center',
anchor: 'center',
font: {
size: '18',
weight: '700'
},
rotation: 270,
formatter: function (value, context) {
return value !== 0 ? value : null;
}
}
},
legend: {
onClick: (e) => e.stopPropagation(),
display: true,
position: 'top',
labels: {
fontFamily: '\'Montserrat\', sans-serif',
fontSize: 14,
fontColor: '#000'
}
},
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
return tooltipItem.yLabel.toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
}
}
},
scales: {
xAxes: [{
stacked: true,
ticks: {
fontSize: 15,
fontStyle: 'normal',
padding: 100
}
},
{
type: 'category',
offset: true,
position: 'top',
ticks: {
fontColor: "#000",
fontSize: 18,
fontStyle: 'bold',
callback: function (value, index, values) {
return "";
}
}
}
],
yAxes: [{
stacked: true,
ticks: {
fontSize: 15,
fontStyle: 'normal'
},
}],
},
animation: {
duration: 1,
onComplete: function () {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
var fontSize = 15;
var fontStyle = 'normal';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'center';
this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
if (dataset.data[index] > 0) {
if(dataset.stack == '0')
{
var data = dataset.data[index].toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
ctx.save();
ctx.translate(bar._model.x, bar._model.y + bar.height());
ctx.rotate(0.5 * Math.PI);
ctx.fillText(data, 35, 0);
ctx.restore();
}
else if(dataset.stack == '1' && dataset.label == 'EXPENSES PLAN')
{
var data = dataset.data[index].toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
ctx.save();
ctx.translate(bar._model.x, bar._model.y);
ctx.rotate(-0.5 * Math.PI);
ctx.fillText(data, 35, 0);
ctx.restore();
}
else if(dataset.stack == '1' && dataset.label == 'SALARY PLAN')
{
var data = dataset.data[index].toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
ctx.save();
ctx.translate(bar._model.x, bar._model.y + bar.height());
ctx.rotate(0.5 * Math.PI);
ctx.fillText(data, 35, 0);
ctx.restore();
}
else if(dataset.stack == '2')
{
var data = dataset.data[index].toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
ctx.save();
ctx.translate(bar._model.x, bar._model.y + bar.height());
ctx.rotate(0.5 * Math.PI);
ctx.fillText(data, 35, 0);
ctx.restore();
}
else if(dataset.stack == '3' && dataset.label == 'ACTUAL EXPENSES')
{
var data = dataset.data[index].toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
ctx.save();
ctx.translate(bar._model.x, bar._model.y);
ctx.rotate(-0.5 * Math.PI);
ctx.fillText(data, 35, 0);
ctx.restore();
}
else if(dataset.stack == '3' && dataset.label == 'ACTUAL SALARY')
{
var data = dataset.data[index].toFixed().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1 ');
ctx.save();
ctx.translate(bar._model.x, bar._model.y + bar.height());
ctx.rotate(0.5 * Math.PI);
ctx.fillText(data, 35, 0);
ctx.restore();
}
}
});
});
}
}
}
new Chart(ctx, {
type: "bar",
data: {
labels: MONTHS,
datasets: dataArray
},
options: options
});
}

Chart.js - Draw horizontal line on horizontal bar chart

I'm trying to achieve the following chart but i am not able to build it.
I was trying with this code (using https://github.com/chartjs/chartjs-plugin-annotation) but i think the solution is not perfect. The value of line "Días meta" needs to be configurable, so the line must be re-drawn as its value changes and the horizontal bar's dataset also changes.
The code:
<script>
var color = Chart.helpers.color;
var horizontalBarChartData = {
//labels: ['7', '6', '5', '4', '3', '2', '0'],
labels: ['5', '3', '2', '1'],
datasets: [{
label: 'QTA de bultos',
backgroundColor: color('#91B643').alpha(0.5).rgbString(),
borderColor: '#91B643',
borderWidth: 1,
data: [
2,
7,
4,
11
]
}]
};
$(document).ready(function () {
var ctx = document.getElementById('myChart').getContext('2d');
window.myHorizontalBar = new Chart(ctx, {
type: 'horizontalBar',
data: horizontalBarChartData,
options: {
// Elements options apply to all of the options unless overridden in a dataset
// In this case, we are setting the border of each horizontal bar to be 2px wide
elements: {
rectangle: {
borderWidth: 2,
}
},
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Horizontal Bar Chart'
},
hover: {
animationDuration: 0
},
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 = 'left';
ctx.textBaseline = 'center';
this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
var data = dataset.data[index];
ctx.fillStyle = "#000";
ctx.fillText(data, bar._model.x + 5, bar._model.y);
});
});
}
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Días en Almacén'
},
gridLines: {
display: false
}
}
],
xAxes: [{
gridLines: {
display: true
},
ticks: {
beginAtZero: true
}
}
]
},
annotation: {
annotations: [{
type: 'line',
mode: 'horizontal',
scaleID: 'x-axis-0',
value: 1,
borderColor: 'rgb(75, 192, 192)',
borderWidth: 4,
label: {
enabled: true,
content: 'Días meta: 999'
}
}]
}
}
});
});
</script>
Example - With original dataset
Example - With change only one value of dataset
Any help will be appreciated, thanks =)

How can I force annotations to always display above columns?

I want the annotations above columns to always BE ABOVE columns. I set annotations.alwaysOutside to true, but whenever a column reaches the roof of the chart, it will position the annotation within the column. If you run the code on JSFiddle you'll see what I mean.
So, how can I force annotations to ALWAYS display above columns?
https://jsfiddle.net/y7ootfoo/
<link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {
packages: ['corechart']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
["Mana Cost", "Cards"],
["0", 1],
["1", 2],
["2", 3],
["3", 4],
["4", 4],
["5", 3],
["6", 2],
["7+", 1],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation",
}, ]);
var options = {
title: "Cards/Mana Cost",
width: '750',
height: '375',
backgroundColor: "#FFF",
enableInteractivity: false,
bar: {
groupWidth: "90%"
},
legend: {
position: "none"
},
annotations: {
alwaysOutside: true,
stem: {
color: "transparent"
},
textStyle: {
fontName: 'Lato',
fontSize: 18.75,
bold: true,
italic: false,
auraColor: 'transparent',
color: "#000"
}
},
chartArea: {
backgroundColor: "#FFF"
},
titleTextStyle: {
color: "#000",
fontName: "Lato",
fontSize: 25,
bold: true,
italic: false
},
vAxis: {
gridlines: {
color: 'transparent'
},
textPosition: "none"
},
hAxis: {
textStyle: {
color: "#000",
fontName: "Lato",
fontSize: 18.75,
bold: true,
italic: false
}
}
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
chart.draw(view, options);
}
</script>
<div id="columnchart_values" style="width: 900px; height: 300px;"></div>
set
var options = {
vAxis: {
viewWindow:{
max: maxV, //maximum value of annotations + 1
},
}}
I also add
chartArea: {
width: '95%',
}
https://jsfiddle.net/damiantt/y7ootfoo/1/
complete code:
<link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {
packages: ['corechart']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
["Mana Cost", "Cards"],
["0", 1],
["1", 2],
["2", 3],
["3", 4],
["4", 4],
["5", 3],
["6", 2],
["7+", 1],
]);
var maxV = 0;
for (var i = 0; i < data.getNumberOfRows(); i++) {
if(data.getValue(i, 1) > maxV) {
maxV = data.getValue(i, 1);
}
}
maxV++;
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation",
}, ]);
var options = {
title: "Cards/Mana Cost",
width: '750',
height: '375',
backgroundColor: "#FFF",
enableInteractivity: false,
bar: {
groupWidth: "90%"
},
legend: {
position: "none"
},
annotations: {
alwaysOutside: true,
stem: {
color: "transparent"
},
textStyle: {
fontName: 'Lato',
fontSize: 18.75,
bold: true,
italic: false,
auraColor: 'transparent',
color: "#000"
}
},
chartArea: {
width: '95%',
backgroundColor: "#FFF"
},
titleTextStyle: {
color: "#000",
fontName: "Lato",
fontSize: 25,
bold: true,
italic: false
},
vAxis: {
viewWindow:{
max:maxV,
},
gridlines: {
color: 'transparent'
},
textPosition: "none"
},
hAxis: {
textStyle: {
color: "#000",
fontName: "Lato",
fontSize: 18.75,
bold: true,
italic: false
}
}
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
chart.draw(view, options);
}
</script>
<div id="columnchart_values" style="width: 900px; height: 300px;"></div>