Add spaces/margin between bars - Chart.js - javascript

How can I add white spaces/margin between bars with Chart.js 3.0 ? I didn't find anything to process like the image
What I want
My code looks like this and makes this :
What I have
datasets: [{
categoryPercentage: 1.0,
barPercentage: 0.8,
}]
},
options: {
onHover() {},
indexAxis: 'y',
maintainAspectRatio: false,
}
full code here : https://codepen.io/mateofaivre/pen/zYdYgmB

You should set the categoryPercentage to lower value like 0.8 and barPercentage to 1.
Graphical info about categoryPercentage vs barPercentage:
// categoryPercentage: 1.0
// barPercentage: 1.0
Bar: | 1.0 | 1.0 |
Category: | 1.0 |
Sample: |===========|
// categoryPercentage: 1.0
// barPercentage: 0.5
Bar: |.5| |.5|
Category: | 1.0 |
Sample: |==============|
// categoryPercentage: 0.5
// barPercentage: 1.0
Bar: |1.0||1.0|
Category: | .5 |
Sample: |==================|
EDIT:
You can get the bar width from the metasets of the chart and use that to draw it on the chart like so:
const plugin = {
id: 'background',
beforeDraw: (chart, args, opts) => {
if (!opts.color) {
return;
}
const {
ctx,
chartArea,
_metasets
} = chart;
ctx.fillStyle = opts.color;
_metasets.forEach(meta => {
meta.data.forEach(data => {
if (data.horizontal) {
ctx.fillRect(chartArea.left, (data.y - (data.height / 2)), chartArea.width, data.height)
} else {
ctx.fillRect((data.x - (data.width / 2)), chartArea.top, data.width, chartArea.height)
}
})
});
}
}
Chart.register(plugin);
var colors = [];
for (var i = 0; i < 5; i++) {
colors.push('#5671DB');
}
var config = {
type: 'bar',
data: {
labels: ['Commerce, vente', 'Transport', 'Bureautique', 'Accueil', 'Santé', 'Secrétariat', 'Nettoyage', 'Sécurité', 'Mécanique', 'Agro-alimentaire'],
datasets: [{
data: [23.8, 17.7, 13, 9.5, 7.8, 7, 5.5, 5, 4.5, 3.5],
backgroundColor: colors,
hoverBackgroundColor: colors,
borderColor: colors,
}],
},
options: {
onHover() {},
indexAxis: 'y',
barPercentage: 0.8,
//barThickness: 60,
// maxBarThickness: 60,
categoryPercentage: 1.0,
maintainAspectRatio: true,
responsive: true,
plugins: {
background: {
color: '#CDECEF'
},
title: {
display: false,
text: "Les 10 principaux domaines d'emploi",
align: 'start',
fullSize: true,
color: '#324488',
font: {
size: 24,
family: 'Arial',
}
},
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(255,255,255,0)',
displayColors: false,
titleFont: {
size: 0,
},
titleMarginBottom: 0,
titleSpacing: 0,
bodyFont: {
size: 25,
weight: 700
},
xAlign: 'right',
callbacks: {
label: (item) => (`${item.parsed.x} %`),
},
},
},
scales: {
y: {
beginAtZero: true,
ticks: {
color: "#34478B",
font: {
size: 18,
},
stepSize: 1,
beginAtZero: true
},
},
x: {
ticks: {
color: "#25C8C9",
font: {
size: 14
},
stepSize: 1,
beginAtZero: true
},
}
}
},
};
var ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, config);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<canvas id="myChart"></canvas>
codePen

If reducing the bar size is not a problem you could add barPercentage to your options.
Like this:
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
barPercentage: 0.8
}
};
Bar Chart | Charts.js

Related

How to remove all gridlines, border and show only ticks on a chartjs horizontal bar chart

Following on from the answer in this post
I have the following chart which can also be found here
const d0 = new Date("2023-02-15T00:00:00.721Z").getTime()
const d1 = new Date("2023-02-15T01:00:00.721Z").getTime()
const d2 = new Date("2023-02-15T02:30:00.721Z").getTime()
const d3 = new Date("2023-02-15T03:20:00.721Z").getTime()
const d4 = new Date("2023-02-15T05:05:00.721Z").getTime()
let values = [d0, d1, d2, d3, d4];
let data = {
labels: [''],
datasets: [{
label: 'up',
axis: 'y',
data: [d1],
backgroundColor: 'red',
},{
label: 'down',
axis: 'y',
data: [d2],
backgroundColor: 'yellow',
},{
label: 'out',
axis: 'y',
data: [d3],
backgroundColor: 'green',
},{
label: 'up',
axis: 'y',
data: [d4],
backgroundColor: 'red',
}
]
};
const config = {
data,
type: 'bar',
options:{
elements: {
bar: {
borderWidth: 0
}
},
ticks: {
display: true
},
interaction: {
mode: 'dataset'
},
tooltip: {
mode: 'dataset'
},
hover: {
mode: 'dataset'
},
onClick: function (e) {
// debugger;
var activePointLabel =
this.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)
alert(activePointLabel[0].datasetIndex);
}
,
plugins: {
legend: {
display: false,
},
title: {
display: false,
},
},
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
grid: {
display: true
},
min: d0,
ticks: {
callback: function(value, index, ticks) {
return moment(value).format('HH:mm');
}
},
// afterBuildTicks: axis => axis.ticks = values.map(v => ({ value: v }))
},
y: {
grid: {
display: false
},
stacked: true
},
}
}};
new Chart(document.getElementById("chart"), config);
This produces this...
]1
I would like to get rid of all the grids lines , except the ticks, but if I set the gird displays false the tick also disappear, and it also leave a border around the chart, etg something like
Is there a way to do this?
Just add border: {display: false}, to the scales configuration. (here is the link to the documentation)
...
scales: {
x: {
border: {
display: false,
},
...
},
...
}
...
Update added full running example:
const d0 = moment.duration('07:00:00').asMinutes();
const d1 = moment.duration('09:00:00').asMinutes();
const d2 = moment.duration('10:45:00').asMinutes();
const d3 = moment.duration('17:35:00').asMinutes();
const d4 = moment.duration('19:00:00').asMinutes();
let values = [d0, d1, d2, d3, d4];
let data = {
labels: [''],
datasets: [{
label: 'up',
axis: 'y',
data: [d1],
backgroundColor: 'red',
},{
label: 'down',
axis: 'y',
data: [d2],
backgroundColor: 'yellow',
},{
label: 'out',
axis: 'y',
data: [d3],
backgroundColor: 'green',
},{
label: 'up',
axis: 'y',
data: [d4],
backgroundColor: 'red',
}
]
};
const config = {
data,
type: 'bar',
options:{
plugins: {
tooltip: {
mode: 'dataset',
callbacks: {
label: function(item){
return moment().startOf('day').add({ minute: item.raw}).format('HH:mm');
}
}
},
legend: {
display: false,
},
title: {
display: false,
},
},
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
min: d0,
border: { display: false },
ticks: {
callback: function(value, index, ticks) {
return moment().startOf('day').add({ minute: value}).format('HH:mm');
}
},
afterBuildTicks: axis => axis.ticks = values.map(v => ({ value: v }))
},
y: {
stacked: true,
grid: { display: false },
},
}
}};
new Chart(document.getElementById("chart"), config);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<script src="//cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="//cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
<div class="chart" style="height:84px; width:350px;">
<canvas id="chart" ></canvas>
</div>
use tickColor (see below config) for v 3.8.2
scales: {
x: {
...
grid: {
display: true,
drawTicks: true, //show ticks
borderColor: "transparent", //horizontal line color above ticks (x-axis)
color: "transparent", //grid lines color
tickColor: "#868e96" //ticks color (little line above points)
},
},
...
}

change axis scale to be round numbers instead of decimal - chart.js

I'm working with chart.js and I can't seem to be able to change the scale of the Y axis to show whole numbers, in this example I would like to have just round numbers in the scale (1,2,3,4,5) instad of the decimal (0 -0,5 - 1,0 - 1,5 - 2,0 - etc)
I'm using a vertical Bar chart from here: https://www.chartjs.org/docs/latest/samples/bar/vertical.html
and my current setup is this:
var setVirtualBarChart = function (element, viewModel) {
var chArea = element.getContext("2d");
var chartConfig = {
type: 'bar',
data: {
labels: ['Categories'],
datasets: [
{
minBarLength: 2,
label: '0-7 days',
barPercentage: 0.75,
categoryPercentage: 0.75,
data: viewModel.ZeroToSevenDaysUser(),
backgroundColor: window.chartColors.BrightVisibleGreen
},
{
minBarLength: 2,
label: '8-30 days',
barPercentage: 0.75,
categoryPercentage: 0.75,
data: viewModel.SevenToThirtyDaysUser(),
backgroundColor: window.chartColors.Orange
},
{
minBarLength: 2,
label: '30+ test days',
barPercentage: 0.75,
categoryPercentage: 0.75,
data: viewModel.ThirtyPlusDaysUser(),
backgroundColor: window.chartColors.BrightRed
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [
{
stacked: false,
display: true,
scaleLabel: {
display: true,
//labelString: 'Categories',
gridLines: {
offsetGridLines: true
}
}
}
],
yAxes: [
{
stacked: false,
display: true,
scaleLabel: {
display: true,
labelString: 'Number of invoices'
},
ticks: {
precision: 0,
min: 0
}
}
]
}
}
};
VirtualBarChart = new Chart(chArea, chartConfig);
};
You are using v2 syntax while using v3, in v3 all scales are objects and no arrays anymore. For all changes please read the migration guide
Exaple:
const options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow"],
datasets: [{
label: '# of Votes',
data: [1, 2.5, 1.5],
backgroundColor: ["Red", "Blue", "Yellow"]
}]
},
options: {
scales: {
y: {
ticks: {
stepSize: 1
},
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
</body>

Chartjs fixed range on X axis and custom labels

I'm trying to create a scatter plot with Chartjs.
I want to have few datasets centered around one X value, and three Y values.
When I can't set the custom X labels for my dataset, and also can't set a fixed range for X axes.
This is how I generate the data:
function generateData(n, xCenter, yCenter) {
var data = [];
var spread = 0.2
for (var i = 0; i < n; i++) {
data.push({
x: (Math.random() - 0.5)*spread + xCenter,
y: (Math.random() - 0.5)*spread + yCenter
})
}
return data
}
var scatterChartData = {
datasets: [
{
label: 'My First dataset',
backgroundColor: "#0000FF",
data: generateData(100, 1, 2)
},
{
label: 'My Second dataset',
backgroundColor: "#00FF00",
data: generateData(50, 1, 3)
},
{
label: 'My Second dataset',
backgroundColor: "#00FF00",
data: generateData(50, 1, 4)
},
]
}
Here are the scatter options:
var scatterOptions = {
tooltips: {
enabled: true
},
responsive: true, // Instruct chart js to respond nicely.
maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height
responsive: true,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display: false,
ticks: {
min: 0,
max: 10,
stepSize: 0.01
}
}
}],
yAxes: [{
gridLines: {
display: true,
ticks: {
stepSize: 0.01,
suggestedMin: 0.5,
suggestedMax: 5
}
}
}]
}
}
And this is the plot:
var myChart = new Chart(ctx, {
showTooltips: false,
type: 'scatter',
data: scatterChartData,
options: scatterOptions
});

ChartJS makes unwanted horizontal line on Safari

I'm currently working with ChartJS.
It works fine on Firefox and Chrome.
On Safari there is horizontal lines which appear. (here there is one good on orange and two others unwanted )
I have a lot of datapoint (2 lines of 1600 data point). I don't know if it could be a cause.
My code is here.
In some other part, I update time uni and time min.
_displayChart: function(label1, label2){
var timeFormat = 'DD/MM/YYYY HH:mm';
var ctx = document.getElementById(this.heading).getContext('2d');
const data = {
// Labels should be Date objects
//labels:this._stats[1],
datasets: [{
fill: false,
label: label1,
data: this._stats[2],
borderColor: '#fe8b36',
pointRadius: 0,
backgroundColor: [
'#fe8b36'
]
},{
label: label2,
fill: false,
data: this._stats[3],
borderWidth: 1,
pointRadius: 0,
borderColor: 'rgba(99, 100, 200, 1)',
backgroundColor: [
'rgba(99, 100, 200, 0.2)'
]
}]
}
const options = {
type: 'line',
data: data,
options: {
responsive: false,
fill: false,
responsive: true,
maintainAspectRatio:!this._isMobile(),
max: this.max,
hover: {
// Overrides the global setting
mode: 'index'
},
annotation: {
drawTime: 'beforeDatasetsDraw',
events: ['click'],
annotations: []
},
legend: {
labels: {
filter: function(legendItem, chartData) {
if(legendItem.datasetIndex == 2 || legendItem.datasetIndex == 3 ){
return false;
}
return true;
}
}
},
tooltips: {
mode:'index',
intersect : false,
callbacks: {
title: function(tooltipItems, data) {
return tooltipItems[0].xLabel.format(timeFormat);
},
label: function(tooltipItems, data) {
return tooltipItems.yLabel+'%';
}
}
},
scales: {
xAxes: [{
type: 'time',
display: true,
time:{
unit:'day',
min:moment(Date.now()-this.monthTs),
max:this._stats[1][this._stats[1].length]
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
},
display: true
}]
}
}
}
this._chart = new Chart(ctx, options);
},
When I'm applying this, I have no problem:
this._chart.options.scales.xAxes[0].time.unit = 'month';
this._chart.options.scales.xAxes[0].time.stepSize = 1;
this._chart.options.scales.xAxes[0].time.min = this._stats[1][0];
this._chart.options.scales.xAxes[0].time.max = this._stats[1][this._stats[1].length-1];
Thanks

chart.js v2: Align time scale labels with the center of the bars

I am trying to align the generated time scale labels using Chart.js v2.2 with the centre of the bars of a bar chart. I have tried the offsetGridLines option but this seems to have no effect when using Xaxis scale type time.
Here is an example, maybe I have missed something:
<div id="container" style="width: 75%;">
<canvas id="canvas"></canvas>
</div>
<script>
var barChartData = {
labels: ["2015-01-01", "2015-02-01", "2015-03-01", "2015-04-01", "2015-05-01", "2015-07-01"],
datasets: [{
label: 'Dataset 1',
backgroundColor: "rgba(220,220,220,0.5)",
data: [10, 4, 5, 7, 2, 3]
}]
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
elements: {
rectangle: {
borderWidth: 2,
borderColor: 'rgb(0, 255, 0)',
borderSkipped: 'bottom'
}
},
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Bar Chart'
}
,
scales: {
xAxes: [{
categoryPercentage: .5,
barPercentage: 1,
type: 'time',
scaleLabel: {
display: true,
labelString: 'Year-Month'
},
time: {
min: '2014-12-01' ,
max: '2015-12-01',
unit: 'month',
displayFormats: {
month: "MMM YY"
}
},
gridLines: {
offsetGridLines: false,
drawTicks: true,
display: true
},
stacked: true
}],
yAxes: [{
ticks: {
beginAtZero: true
},
stacked: true
}]
}
}
});
};
</script>
This fiddle may help to place the data label in the center of the bar
https://jsfiddle.net/tea8dhgy/
<div id="container" style="width: 75%;">
<canvas id="canvas"></canvas>
</div>
var barChartData = {
labels: ["2015-01-01", "2015-02-01", "2015-03-01", "2015-04-01", "2015-05-01", "2015-07-01"],
datasets: [{
label: 'Dataset 1',
backgroundColor: "rgba(220,220,220,0.5)",
data: [10, 4, 5, 7, 2, 3]
}]
};
var ctx = document.getElementById("canvas").getContext("2d");
new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
elements: {
rectangle: {
borderWidth: 2,
borderColor: 'rgb(0, 255, 0)',
borderSkipped: 'bottom'
}
},
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Bar Chart'
},
scales: {
xAxes: [{
categoryPercentage: .5,
barPercentage: 1,
type: 'time',
scaleLabel: {
display: true,
labelString: 'Year-Month'
},
time: {
// min: '2014-12-01' ,
// max: '2015-12-01',
unit: 'month',
displayFormats: {
month: "MMM YY"
}
},
gridLines: {
offsetGridLines: false,
drawTicks: true,
display: true
},
stacked: true
}],
yAxes: [{
ticks: {
beginAtZero: true
},
stacked: true
}]
},
animation: {
onComplete: function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(10, "bold", 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) {
//var data = dataset.data[index];
var data = dataset.data[index];
console.log(bar);
if (data > 0) {
ctx.fillText(data, bar._model.x, bar._model.base - (bar._model.base - bar._model.y) / 2 - 5);
}
});
});
}
}
}
});
I was able to get a working chart by removing the min and max values set.
Here is the JSFiddle
Was the following image the desired outcome?

Categories