On this jsfiddle https://jsfiddle.net/rvbrr0Lu/30/. The 'g' char in the ScaleLabel for the x-axis is cut off. I tried adding some padding to the ScaleLabel, but it seemed to have no effect. What should I do so the 'g' on the x-axis is not cut off?
Here is my js code.
var canvas = document.getElementById('myChart');
var raw = [
{start: '0', end: '10', data: [{}]},
{start: '10', end: '20', data: [{},{},{}]},
{start: '20', end: '30', data: [{},{}]},
{start: '30', end: '40', data: [{},{},{},{}]},
{start: '40', end: '50', data: [{},{},{},{},{}]},
{start: '50', end: '60', data: [{},{},{},{},{},{}]},
];
var data = {
labels: raw.map((r) => '$' + r.start).concat('$' + raw[raw.length - 1].end),
datasets: [
{
backgroundColor: ["red","orange","yellowgreen","green","violet", "rebeccapurple"],
data: raw.map((r) => r.data.length*(1.73 * Math.random())),
}
]
};
function getYTicks() { return [0, 10]};
function formatz(v) { return 'E' + v; };
function formatY(v) { return '$' + v + '.00'; };
var option = {
legend: {
display: false,
},
layout: {
padding: {
left: 5,
top: 5,
right: 5,
bottom: 5,
},
},
scales: {
yAxes:[{
scaleLabel: {
display: true,
labelString: 'Y',
fontFamily: 'Lato',
fontSize: 14,
},
ticks: {
beginAtZero: true,
padding: 10,
fontFamily: 'Lato',
fontSize: 14,
},
afterBuildTicks: getYTicks(),
gridLines: {
display: true,
color: 'rgba(50,50,50,0.2)',
zeroLineColor: 'rgba(50,50,50,0.5)',
zeroLineWidth: 2,
drawTicks: true,
tickMarkLength: 4,
},
}],
xAxes:[{
barPercentage: 0.8,
categoryPercentage: 1,
gridLines: {
display: false,
tickMarkLength: 10,
color: 'rgba(50,50,50,0.1)',
drawTicks: false,
offsetGridLines: false,
zeroLineColor: 'rgba(50,50,250,0.5)',
zeroLineWidth: 5,
},
scaleLabel: {
display: true,
labelString: 'Pages',
padding: 300,
fontFamily: 'Lato',
fontSize: 14,
},
ticks: {
beginAtZero: true,
callback: formatz,
fontFamily: 'Lato',
fontSize: 14,
},
}]
}
};
var myBarChart = Chart.Bar(canvas,{
data:data,
options:option
});
Use the latest version of Chart.js (2.7.1):
var canvas = document.getElementById('myChart');
var raw = [
{start: '0', end: '10', data: [{}]},
{start: '10', end: '20', data: [{},{},{}]},
{start: '20', end: '30', data: [{},{}]},
{start: '30', end: '40', data: [{},{},{},{}]},
{start: '40', end: '50', data: [{},{},{},{},{}]},
{start: '50', end: '60', data: [{},{},{},{},{},{}]},
];
var data = {
labels: raw.map((r) => '$' + r.start).concat('$' + raw[raw.length - 1].end),
datasets: [
{
backgroundColor: ["red","orange","yellowgreen","green","violet", "rebeccapurple"],
data: raw.map((r) => r.data.length*(1.73 * Math.random())),
}
]
};
function getYTicks() { return [0, 10]};
function formatz(v) { return 'E' + v; };
function formatY(v) { return '$' + v + '.00'; };
var option = {
legend: {
display: false,
},
layout: {
padding: {
left: 10,
top: 10,
right: 10,
bottom: 10,
},
},
scales: {
yAxes:[{
scaleLabel: {
display: true,
labelString: 'Y',
fontFamily: 'Lato',
fontSize: 14,
},
ticks: {
beginAtZero: true,
padding: 10,
fontFamily: 'Lato',
fontSize: 14,
},
afterBuildTicks: getYTicks(),
gridLines: {
display: true,
color: 'rgba(50,50,50,0.2)',
zeroLineColor: 'rgba(50,50,50,0.5)',
zeroLineWidth: 2,
drawTicks: true,
tickMarkLength: 4,
},
}],
xAxes:[{
barPercentage: 0.8,
categoryPercentage: 1,
gridLines: {
display: false,
tickMarkLength: 10,
color: 'rgba(50,50,50,0.1)',
drawTicks: false,
offsetGridLines: false,
zeroLineColor: 'rgba(50,50,250,0.5)',
zeroLineWidth: 5,
},
scaleLabel: {
display: true,
labelString: 'Pages',
padding: 20,
fontFamily: 'Lato',
fontSize: 14,
},
ticks: {
beginAtZero: true,
callback: formatz,
fontFamily: 'Lato',
fontSize: 14,
},
}]
}
};
var myBarChart = Chart.Bar(canvas,{
data:data,
options:option
});
#myChart {
border: 1px solid black;
}
<script src="https://unpkg.com/moment#2.14.1/min/moment.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
<canvas id="myChart" width="400" height="300"></canvas>
Related
We are using react chart js but the problem occurs when we try to show multi-line charts in small widgets with high y-axis values.
Overflow occurs in smaller widths and large y axes numbers. I already try a thousand suffixes but it doesn't work. Is it possible to keep the y-axis constant by making the x-axis smaller? Or handle it responsive.
function randomTwoNumbers(n1, n2) {
return Math.floor(Math.random() * (n2 - n1 + 1) + n1)
}
function generateData(count) {
let data = []
for (let index = 0; index < count; index++) {
data.push({
x: `2022-07-${index}T00:00:00.000Z`,
y: randomTwoNumbers(1000000, 9999999)
})
}
return data
}
const data = {
datasets: [
{
data: generateData(100),
label: 'Temperature',
borderColor: '#236EF1',
tension: 0.5,
pointRadius: 1,
pointHoverRadius: 5,
pointHitRadius: 20,
yAxisID: 'y0'
},
{
data: generateData(100),
label: 'Humidity',
borderColor: '#CA840C',
tension: 0.5,
pointRadius: 1,
pointHoverRadius: 5,
pointHitRadius: 20,
yAxisID: 'y1'
}
]
}
const options = {
responsive: true,
resizeDelay: 300,
scales: {
x: {
display: true,
grid: {
borderColor: '#5E646E',
tickColor: '#5E646E',
display: true,
drawOnChartArea: false
},
ticks: {
autoSkip: false,
maxRotation: 0,
font: {
size: 10,
family: 'Inter',
lineHeight: '12px',
weight: '500'
}
},
time: {
unit: 'day',
displayFormats: {
minute: 'p',
hour: 'p',
day: 'MMM, do'
}
},
type: 'time',
offset: true,
adapters: {
date: {
locale: {
code: 'en-US',
formatLong: {},
localize: {},
match: {}
}
}
}
},
y0: {
display: true,
grid: {
borderColor: '#5E646E',
tickColor: '#5E646E',
display: true,
drawOnChartArea: false
},
ticks: {
font: {
size: 10,
family: 'Inter',
lineHeight: '12px',
weight: '500'
}
},
stack: 'single',
offset: false
},
y1: {
display: true,
grid: {
borderColor: '#5E646E',
tickColor: '#5E646E',
display: true,
drawOnChartArea: false
},
ticks: {
font: {
size: 10,
family: 'Inter',
lineHeight: '12px',
weight: '500'
}
},
stack: 'single',
offset: false
}
},
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
title: {
display: false
},
tooltip: {
displayColors: false
}
}
}
var config = {
type: 'line',
data,
options
}
var ctx = document.getElementById('canvas').getContext('2d')
window.myLine = new Chart(ctx, config)
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.2/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-adapter-moment/1.0.1/chartjs-adapter-moment.min.js"></script>
<div style="width: 200px">
<canvas id="canvas"></canvas>
</div>
I try to create a multi axis chart using chart.js ver 3.6.0 but it look nothing like the one displayed in their example found here chart
This is the code I use.
<canvas id="canvas"></canvas>
<script>
const ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.height = 200;
const labels = "11/1/2021,11/2/2021,11/3/2021,11/4/2021,11/5/2021,11/6/2021,11/7/2021,11/8/2021,11/9/2021,11/10/2021";
const data = {
labels: labels,
datasets: [
{
label: "South",
data: "6,4,2,4,3,1,0,9,3,0",
borderColor: "#0d47a1",
backgroundColor: "#2196f3",
yAxisID: "y",
},
{
label: "North",
data: "72,97,88,143,102,0,0,153,100,0",
borderColor: "#e65100",
backgroundColor: "#ff9800",
yAxisID: "y1",
},
],
};
const config = {
type: "line",
data: data,
options: {
responsive: true,
interaction: {
mode: "index",
intersect: false,
},
stacked: false,
plugins: {
title: {
display: true,
text: "Test",
},
},
scales: {
y: {
type: "linear",
display: true,
position: "left",
},
y1: {
type: "linear",
display: true,
position: "right",
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
x: {
ticks: {
maxRotation: 65,
minRotation: 65,
fontSize: 11,
},
},
},
},
};
window.myLine = new Chart(ctx, config);
</script>
Why is the lines not connected, and why is the y axis not displaying each datasets max value?
Mine looks like this..
This is because you provide the labels and data as strings while it should be an array with strings for the labels, same goes for the data field:
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
<script>
const ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.height = 200;
const labels = ['11/1/2021', '11/2/2021', '11/3/2021', '11/4/2021', '11/5/2021', '11/6/2021', '11/7/2021', '11/8/2021', '11/9/2021', '11/10/2021'];
const data = {
labels: labels,
datasets: [{
label: 'South',
data: ['6', '4', '2', '4', '3', '1', '0', '9', '3', '0'],
borderColor: '#0d47a1',
backgroundColor: '#2196f3',
yAxisID: 'y',
},
{
label: 'North',
data: ['72', '97', '88', '143', '102', '0', '0', '153', '100', '0'],
borderColor: '#e65100',
backgroundColor: '#ff9800',
yAxisID: 'y1',
}
]
};
const config = {
type: 'line',
data: data,
options: {
responsive: true,
interaction: {
mode: 'index',
intersect: false,
},
stacked: false,
plugins: {
title: {
display: true,
text: 'Test'
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
},
y1: {
type: 'linear',
display: true,
position: 'right',
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
x: {
ticks: {
maxRotation: 65,
minRotation: 65,
fontSize: 11
}
}
}
},
};
new Chart(ctx, config);
</script>
I want to make side labels for double horizontal bar on both side like this: pic 1, pic 2
can someone help me idk how to do it, im new in react and chartjs
this post continued from: How to make multiple horizontal bar chartjs
here's what i code:
this the data:
data for chart
export const dataPasienKeluarMasuk = {
type: 'bar',
labels: [
[0, 1, 2, 3,4], // expect output 0 - 4
[5, 6, 7, 8, 9], // expect output 5 - 9
[10, 14], // ext..
[15, 19],
[20, 24],
[25, 29],
[30, 34],
],
datasets: [
{
label: 'Pasien Masuk',
xAxisID: 'A',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
xAxisID: 'A',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
],
}
this the chart:
multiple y horizontal bar
import { HorizontalBar } from 'react-chartjs-2'
import { dataPasienKeluarMasuk } from ...blabla
<HorizontalBar
data={dataPasienKeluarMasuk}
height={227}
options={{
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
display: true,
position: 'bottom',
},
scales: {
xAxes: [
{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Jumlah Pasien (orang)',
},
ticks: {
// Include a dollar sign in the ticks
callback: (value) => Math.abs(value),
},
},
],
yAxes: [
{
stacked: true,
ticks: {
display: true,
reverse: true,
},
},
],
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
let ds = data.datasets[tooltipItem.datasetIndex]
return (
ds.label + ': ' + Math.abs(ds.data[tooltipItem.index])
)
},
},
},
}}
/>
You can obtain the desired result by defining a second y-axis as follows:
{
type: 'category',
position: 'right',
offset: true,
ticks: {
reverse: true,
},
gridLines: {
display: false
}
}
Please take a look at your amended and runnable code below:
new Chart(document.getElementById('canvas'), {
type: 'horizontalBar',
data: {
labels: ['0-4', '5-9', '10-14', '15-19', '20+'],
datasets: [{
label: 'Pasien Masuk',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
data: [-100, -75, -60, -75, -70],
backgroundColor: 'blue',
},
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
position: 'bottom',
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
let ds = data.datasets[tooltipItem.datasetIndex];
return ds.label + ': ' + Math.abs( ds.data[tooltipItem.index]);
}
}
},
scales: {
xAxes: [{
stacked: true,
ticks: {
callback: value => Math.abs(value)
}
}],
yAxes: [{
stacked: true,
ticks: {
reverse: true,
}
},
{
type: 'category',
position: 'right',
offset: true,
ticks: {
reverse: true,
},
gridLines: {
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>
I want to make horizontal bar chart using chartjs in react like this: chart i want to make
but i end up doing like this chart i make
can someon help me please, im new in react and chartjs
Here's the continuation of this post: How to make labels on both side from horizontal bar chart js
here's what i code:
this the data:
export const dataPasienKeluarMasuk = {
type: 'bar',
labels: [
[0, 1, 2, 3,4], // expect output 0 - 4
[5, 6, 7, 8, 9], // expect output 5 - 9
[10, 14], // ext..
[15, 19],
[20, 24],
[25, 29],
[30, 34],
],
datasets: [
{
label: 'Pasien Masuk',
xAxisID: 'A',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
xAxisID: 'A',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
],
}
here's the chart:
import { HorizontalBar } from 'react-chartjs-2'
import { dataPasienKeluarMasuk } from ...blabla
<HorizontalBar
data={dataPasienKeluarMasuk}
height={227}
options={{
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
display: true,
position: 'bottom',
},
scales: {
xAxes: [
{
id: 'A',
position: 'left',
},
],
},
}}
/>
You should define both axes as stacked:
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
In order to see only positive values displayed on the x-axis ticks, you need to define a ticks.callback function on the x-axis.
ticks: {
callback: value => Math.abs(value)
}
To have only positive values displayed in the tooltips, you further need to define a tooltips.callback.label functions as shown below.
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
let ds = data.datasets[tooltipItem.datasetIndex];
return ds.label + ': ' + Math.abs( ds.data[tooltipItem.index]);
}
}
},
Please take a look at the runnable code snippet below and see how it works (this is a pure Chart.js solution but it should easily be adaptable to react-chart.js).
new Chart(document.getElementById('canvas'), {
type: 'horizontalBar',
data: {
labels: ['a', 'b', 'c', 'd', 'e'],
datasets: [{
label: 'Pasien Masuk',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
position: 'bottom',
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
let ds = data.datasets[tooltipItem.datasetIndex];
return ds.label + ': ' + Math.abs( ds.data[tooltipItem.index]);
}
}
},
scales: {
xAxes: [{
stacked: true,
ticks: {
callback: value => Math.abs(value)
}
}],
yAxes: [{
stacked: true
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>
this snippet is based from uminder's answer
new Chart(document.getElementById('canvas'), {
type: 'horizontalBar',
data: {
labels: ['a', 'b', 'c', 'd', 'e'],
datasets: [{
label: 'Pasien Masuk',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
display: true,
position: 'bottom',
},
scales: {
xAxes: [{
stacked: true,
ticks: {
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return value < 0? -(value) : value
}
}
}],
yAxes: [{
stacked: true
}]
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
var value = tooltipItem.xLabel;
value = value < 0? -(value) : value
return label + ': ' + value;
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>
I am using the datalabels plugin, and the values overlap if they are too long:
I tried using the diaply auto under plugins datalabels, but it stills overlaps, any ideas what to do so that they dont overlap?
here are my options:
const getOptions = (yAxisDisplayLabel, data, previousOpts, isMobile) => ({
...previousOpts,
layout: {
padding: {
top: 20,
},
},
plugins: {
datalabels: {
font: {
size: isMobile ? 8 : 12,
},
offset: isMobile ? -15 : -20,
anchor: 'end',
formatter: (value, context) => data.datasets[context.datasetIndex].displayValue[context.dataIndex],
display: 'auto',
align: 'start',
},
},
scales: {
yAxes: [{
ticks: {
display: true,
fontColor: '#c8c8c8',
fontSize: isMobile ? 8 : 12,
fontFamily: 'Futura Book',
beginAtZero: true,
},
gridLines: {
drawBorder: false,
},
scaleLabel: {
display: true,
labelString: yAxisDisplayLabel,
},
}],
xAxes: [{
categoryPercentage: isMobile ? 0.8 : 0.7,
barPercentage: 1,
gridLines: {
display: false,
drawBorder: false,
},
}],
},
legend: {
display: false,
},
scaleBeginAtZero: true,
});
The simple, non-technical, answer is of course to write Unit: €/m2 somewhere else on the chart and not an every bar.