So I'm using the datalabels plugin for Chartjs on a bar chart. Each label has data for monthly and 7 days prior. I want the datalabels to be colored red for monthly black for 7 days prior. the color feature in options groups 2 bars together and displays 2 red 2 black 2 red 2 black in chunks as appose to individually.
Heres a link to the outputted chart. https://imgur.com/fqPesYz
import Chart from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
require("../../Row4/Row4Charts/RoundedBars.js");
export default class Cancellations7daysChart extends Component {
Cancellations7daysChart = React.createRef();
componentDidMount() {
const Cancellations7daysChart = this.Cancellations7daysChart.current.getContext(
"2d"
);
new Chart(Cancellations7daysChart, {
type: "bar",
data: {
labels: ["DSL", "FTTC", "FTTP", "GFast"],
datasets: [
{
label: "Monthly",
data: [7, 19, 2, 0],
backgroundColor: [
"rgba(255, 9, 49)",
"rgba(255, 9, 49)",
"rgba(255, 9, 49)",
"rgba(255, 9, 49)"
],
borderColor: [
"rgba(0, 193, 189)",
"rgba(255, 9, 49)",
"rgba(0, 193, 189)",
"rgba(0, 193, 189)"
],
borderWidth: 1,
pointRadius: 4,
},
{
label: "7 days prior",
data: [2, 11, 5, 3],
backgroundColor: [
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)"
],
borderColor: [
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)",
"rgba(208, 210, 211)"
],
borderWidth: 1,
pointRadius: 6,
}
]
},
options: {
maintainAspectRatio: true,
cornerRadius: 6,
cutoutPercentage: 65,
angleLines: {
display: true
},
tooltips: {
enabled: true
},
label: {
usePointStyle: true
},
legend: {
position: "bottom",
labels: {
filter: function (legendItem, Cancellations7daysChart) {
return !legendItem.text.includes("Monthly");
}
}
},
scales: {
ticks: {
maxTickLimit: 1,
max: 15,
display: false
},
//yaxes change
yAxes: [
{
gridLines: {
drawBorder: false,
display: false
},
ticks: {
beginAtZero: true,
display: false
}
}
],
//xaxes change
xAxes: [
{
ticks: {
//Change font here
},
gridLines: {
drawBorder: false,
display: false,
scaleShowLabels: false
}
}
]
},
plugins: {
datalabels: {
color: ["red", "black", "red", "black", "red", "black", "red", "black"],
align: "end",
anchor: "end"
}
}
}
});
}
render() {
return (
<div>
<canvas
id="Cancellations7daysChart"
ref={this.Cancellations7daysChart}
width={360}
height={360}
/>
</div>
);
}
}
You need to make a function to change the colors depending their label:
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
color: function(context) {
var index = context.dataIndex;
var value = context.dataset.data[index];
var valueRed = context.dataset.label;
if(valueRed === 'Monthly') {
return value = 'red';
} else {
return value = '#000';
}
}
}
}
Here is a working example: Plunker example
More info about formatting in the plugin's page: Scriptable Options
Related
I've made a progress bar with the stacked100 plugin. The chart consists of 2 datasets forming the progress bar. The first dataset tooltip is the one I want to always show, the second dataset tooltip will be hidden. I can't figure out how to make the first dataset tooltip to always show.
https://jsfiddle.net/tLcfwvr7/4/
Chart.register(ChartjsPluginStacked100.default);
// setup
const labelChart = ''
const data = {
labels: ['Progress'],
datasets: [{
label: labelChart,
data: [75.455],
backgroundColor: 'rgba(0, 168, 244, 1)',
},
{
label: labelChart,
data: [24.545],
backgroundColor: 'rgba(233, 236, 239, 1)',
}
]
};
// config
const config = {
type: 'bar',
data,
options: {
barThickness: 10,
indexAxis: 'y',
plugins: {
legend: {
display: false
},
tooltip: {
enabled: true,
backgroundColor: 'rgba(50, 50, 50, 1)',
displayColors: false,
yAlign: 'bottom',
caretPadding: 6,
padding: 5,
bodyFont: {
family: "'Poppins', sans-serif",
size: 12,
},
filter: function(tooltipItem) {
return tooltipItem.datasetIndex === 0;
},
callbacks: {
title: () => null,
label: (tooltipItem) => {
const data = tooltipItem.chart.data;
const datasetIndex = tooltipItem.datasetIndex;
const index = tooltipItem.dataIndex;
const rateValue = data.calculatedData[datasetIndex][index];
return `${rateValue}%`;
}
},
},
stacked100: {
enable: true,
replaceTooltipLabel: false,
}
},
scales: {
x: {
grid: {
display: false,
borderColor: 'rgba(0, 0, 0, 0)'
},
ticks: {
display: false
}
},
y: {
beginAtZero: true,
ticks: {
display: false
},
grid: {
display: false,
borderColor: 'rgba(0, 0, 0, 0)'
}
}
},
layout: {
padding: 10
}
}
};
// render init block
const progressChart = new Chart(
document.getElementById('progressChart'),
config
);
I would like to change the direction of scrolling on a horizontal scrollable bar chart in such way scrolling start from right to left (RTL). I'm not sure if it is supported or not. in case, it is not, then is there a way to programmatically scroll to the far right of the chart upon loading to achieve the desired outcome.
const chartsoptions = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5", "6",],
datasets: [{
label: 'OFF',
data: [1, 2, 3, 4, 5, 6],
backgroundColor: [ 'rgba(255, 99, 132, 0.4)', ],
borderColor: [ 'rgb(255, 99, 132)', ],
borderWidth: 1
},{
label: 'On',
data: [6, 5, 4, 3, 2, 1],
backgroundColor: [ 'rgba(75, 192, 192, 0.4)', ],
borderColor: ['rgb(75, 192, 192)', ],
borderWidth: 1
}]
},
options: {
plugins: {
legend: {
display: true,
labels: {
font: {
size: 20,
weight: "bold",
},
}
},
datalabels: {
anchor: 'center',
clamp: true,
display: true,
textAlign: 'center',
borderRadius: 3,
color: "black",
clip: true,
font: {
size: 20,
weight: "bold",
},
},
zoom: {
zoom: { wheel: { enabled: false, }, mode: 'x', },
pan: { enabled: true, mode: 'x', },
limits: { x: { minRange: 3 }, },
}
},
scales: {
x: { ticks: { font: { size: 20, weight: "bold" }, } },
y: { ticks: { font: { size: 20, weight: "bold" }, } },
}
}
}
const ctx = document.getElementById('dailyonoff').getContext('2d');
document.getElementById('dailyonoff').style.backgroundColor = "white";
const chart = new Chart(ctx, chartsoptions);
setTimeout(() => {
chart.zoom(2);
chart.pan({
x: Number.MAX_SAFE_INTEGER
}, undefined, 'default');
}, 10)
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js" integrity="sha256-+8RZJua0aEWg+QVVKg4LEzEEm/8RFez5Tb4JBNiV5xA=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.1.1/chartjs-plugin-zoom.js"></script>
</head>
<body>
<canvas id="dailyonoff" class="onoff" width="300" height="200" ></canvas>
</body>
</html>
I found the solution to navigate (pan) to the end of the graph. just replace:
MAX_SAFE_INTEGER
with:
MIN_SAFE_INTEGER
I have a chart showing website calls the last 7 days. There it is:
Here is the initialization:
varwebsitecalls_chart = new Chart(websitecalls_chartel, {
type: 'line',
data: {
labels: ["Sa", "So", "Mo", "Di", "Mi", "Do", "Fr"],
datasets: [{
label: 'Websitecalls',
data: [0, 0, 0, 0, 0, 0, 0],
borderWidth: 2,
borderColor: '#00000',
backgroundColor: '#ffff',
pointStyle: 'circle',
pointRadius: 7,
cubicInterpolationMode: 'monotone',
tension: 0.4,
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
},
scales: {
x: {
grid: {
display: false,
}
},
y: {
min: 0,
ticks: {
precision: 0,
font: {
family: 'Montserrat',
},
},
grid: {
borderDash: [5, 5],
}
},
}
},
});
Problem:
The Problem is that the chart cuts of the circles when the data is 0 because I set min to 0. I have to set min to 0 because negative websitecalls can not exist. If I do not set it -1 will be displayed. Is there a way to fix this designtechnical issue?
Thanks in advance,
Filip.
No idea why, but defining y.beginAtZero: true instead of y.min: 0 will solve the problem.
Please take a look at your amended and runnable code and see how it works.
new Chart('websitecalls_chartel', {
type: 'line',
data: {
labels: ["Sa", "So", "Mo", "Di", "Mi", "Do", "Fr"],
datasets: [{
label: 'Websitecalls',
data: [0, 0, 0, 0, 0, 0, 0],
borderWidth: 2,
borderColor: '#00000',
backgroundColor: '#ffff',
pointStyle: 'circle',
pointRadius: 7,
cubicInterpolationMode: 'monotone',
tension: 0.4,
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
},
scales: {
x: {
grid: {
display: false,
}
},
y: {
beginAtZero: true,
ticks: {
precision: 0,
font: {
family: 'Montserrat',
},
},
grid: {
borderDash: [5, 5],
}
},
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
<canvas id="websitecalls_chartel" height="80"></canvas>
Chart.js documentation states...
beginAtZero: if true, scale will include 0 if it is not already included.
min: user defined minimum number for the scale, overrides minimum value from data.
Is it possible to select a column in a stack bar chart with a colored border? Like this
I started from here:
https://jsfiddle.net/sdfx/hwx9awgn/
// Return with commas in between
var numberWithCommas = function(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
var dataPack1 = [40, 47, 44, 38, 27, 31, 25];
var dataPack2 = [10, 12, 7, 5, 4, 6, 8];
var dataPack3 = [17, 11, 22, 18, 12, 7, 5];
var dates = ["SN 1.0.1", "SN 1.0.2", "SN 1.0.3", "SN 1.0.4", "SN 1.0.5", "SN 2.0.0", "SN 2.0.1"];
// Chart.defaults.global.elements.rectangle.backgroundColor = '#FF0000';
var bar_ctx = document.getElementById('bar-chart');
var bar_chart = new Chart(bar_ctx, {
type: 'bar',
data: {
labels: dates,
datasets: [{
label: 'Bad Style',
data: dataPack1,
backgroundColor: "#512DA8",
hoverBackgroundColor: "#7E57C2",
hoverBorderWidth: 0
}, {
label: 'Warning',
data: dataPack2,
backgroundColor: "#FFA000",
hoverBackgroundColor: "#FFCA28",
hoverBorderWidth: 0
}, {
label: 'Error',
data: dataPack3,
backgroundColor: "#D32F2F",
hoverBackgroundColor: "#EF5350",
hoverBorderWidth: 0
}, ]
},
options: {
animation: {
duration: 10,
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ": " + numberWithCommas(tooltipItem.yLabel);
}
}
},
scales: {
xAxes: [{
stacked: true,
gridLines: {
display: false
},
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) {
return numberWithCommas(value);
},
},
}],
}, // scales legend: {display: true} } // options } );
Yes what you can do is in the onClick as second argument you get an array with all the active elements. So what you can do is loop over each dataset in your chart and see if the index matches one of the list with active elements.
If this is the case you give it a borderWidth of 1, else you put it to 0. After you did this you call chart variable.update();
To make this work you need to remove the hoverBorderWidth of all datasets and give all datasets a borderColor of yellow
Use attribute borderColor with an array and borderWith with and object.
datasets: [
{
label: 'Bad Style',
data: dataPack1,
backgroundColor: "#512DA8",
borderColor: [
'rgb(243, 255, 51)',
'rgb(81,45,168)',
'rgb(243, 255, 51)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
],
borderWidth: {
top: 0,
right: 4,
bottom: 0,
left: 4
},
},
rgb(243, 255, 51) is yellow color.
To change the color, try this:
var borderColor = [
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
'rgb(81,45,168)',
];
var bar_ctx = document.getElementById('bar-chart');
var bar_chart = new Chart(bar_ctx, {
type: 'bar',
data: {
labels: dates,
datasets: [
{
label: 'Bad Style',
data: dataPack1,
backgroundColor: "#512DA8",
hoverBackgroundColor: "#7E57C2",
hoverBorderWidth: 0,
borderColor: borderColor,
borderWidth: '4',
},
{
label: 'Warning',
data: dataPack2,
backgroundColor: "#FFA000",
hoverBackgroundColor: "#FFCA28",
hoverBorderWidth: 0,
borderColor: borderColor,
borderWidth: '4',
},
{
label: 'Error',
data: dataPack3,
backgroundColor: "#D32F2F",
hoverBackgroundColor: "#EF5350",
hoverBorderWidth: 0,
borderColor: borderColor,
borderWidth: '4',
},
]
},
options: {
onClick: function(e){
var element = this.getElementAtEvent(e);
borderColor[element[0]._index] = 'rgb(244,140,4)';
this.update();
},
animation: {
duration: 10,
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ": " + numberWithCommas(tooltipItem.yLabel);
}
}
},
scales: {
xAxes: [{
stacked: true,
gridLines: { display: false },
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) { return numberWithCommas(value); },
},
}],
}, // scales
legend: {display: true}
} // options
}
);
I want to draw a reference line in the time series chart. I tried to use two x axis and two y axis so I have like two graphs in one. the one would show time scale line and the other one would show linear line (reference line).
image example of what I want it to look like :
I tried in fiddle but its like the two X axis are connected and not scaling separately:
var data = {
labels: [],
datasets: [{
fill: 'none',
label: 'signal1',
backgroundColor: 'rgba(75,192,192,0.4)',
pointRadius: 5,
pointHoverRadius: 7,
borderColor: 'rgba(75,192,192,1)',
borderWidth: 1,
lineTension: 0,
xAxisID: 'xAxis1',
yAxisID: 'yAxis1',
data: [{
x: '2016-07-17',
y: 44
},
{
x: '2016-07-19',
y: 50
},
{
x: '2016-07-22',
y: 84
},
],
}, {
fill: 'none',
label: 'signal2',
lineTension: 0,
xAxisID: 'xAxis2',
yAxisID: 'yAxis2',
data: [{
x: 0,
y: 55
},
{
x: 1,
y: 55
},
]
}],
};
var option = {
scales: {
yAxes: [{
id: 'yAxis1',
offset: true,
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: true,
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 15,
drawBorder: true,
},
ticks: {
beginAtZero: false,
padding: 5,
fontSize: 12,
fontColor: '#222222',
},
}, {
id: 'yAxis2',
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: false,
drawBorder: false,
},
ticks: {
beginAtZero: false,
},
}],
xAxes: [{
id: 'xAxis1',
offset: true,
bounds: 'data',
type: 'time',
distribution: 'linear',
time: {
unit: 'day',
displayFormats: {
day: 'D.M.YYYY',
},
},
gridLines: {
display: true,
color: 'rgba(151, 151, 151, 0.2)',
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 5,
drawBorder: true,
},
ticks: {
source: 'auto',
autoSkip: true,
autoSkipPadding: 30,
maxRotation: 0,
padding: 2,
fontSize: 12,
fontColor: '#222222',
},
}, {
id: 'xAxis2',
type:"linear",
gridLines: {
display: false,
drawBorder: false,
},
}]
}
};
https://jsfiddle.net/2gyk9v5e/15/
This can be done with the Plugin Core API. The API offers different hooks that may be used for executing custom code. In your case, you can use the afterDraw hook to draw the desired lines directly on the canvas using CanvasRenderingContext2D.
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
chart.data.datasets[0].refLines.forEach(r => {
var y = yAxis.getPixelForValue(r.y);
ctx.strokeStyle = r.color;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
});
ctx.restore();
}
}],
Above code assumes that the reference lines are defined inside your dataset through the following definition.
refLines: [
{ y: 45, color: '#0be059' },
{ y: 49, color: '#fc3503' }
]
Please take a look at your amended code and see how it works.
new Chart('canvas', {
type: 'line',
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
chart.data.datasets[0].refLines.forEach(r => {
var y = yAxis.getPixelForValue(r.y);
ctx.strokeStyle = r.color;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
datasets: [{
fill: false,
label: 'signal1',
backgroundColor: 'rgba(75,192,192,0.4)',
pointRadius: 5,
pointHoverRadius: 7,
borderColor: 'rgba(75,192,192,1)',
borderWidth: 1,
lineTension: 0,
data: [
{ x: '2016-07-14', y: 44 },
{ x: '2016-07-15', y: 52 },
{ x: '2016-07-16', y: 45 },
{ x: '2016-07-17', y: 47 },
{ x: '2016-07-18', y: 35 },
{ x: '2016-07-19', y: 46 },
{ x: '2016-07-20', y: 50 },
{ x: '2016-07-21', y: 44 }
],
refLines: [
{ y: 45, color: '#0be059' },
{ y: 49, color: '#fc3503' }
]
}]
},
options: {
scales: {
yAxes: [{
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
display: false,
drawBorder: false
}
}],
xAxes: [{
offset: true,
bounds: 'data',
type: 'time',
time: {
unit: 'day',
displayFormats: {
day: 'D.M.YYYY',
}
},
gridLines: {
color: 'rgba(151, 151, 151, 0.2)',
zeroLineColor: '#979797',
zeroLineWidth: 1,
tickMarkLength: 5,
drawBorder: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="canvas" height="80"></canvas>