I'm using react-chartjs-2 as the chart library for my data visualization.
I need to show one vertical line on a distribution graph. Example:
I have tried to implement as below. I have tried to draw the vertical line by a small math calculation.
Can anyone suggest a better solution than to draw a vertical line on selected X value on the graph?
line_chart_1 = {
datasets: [
{
label: 'My First dataset',
backgroundColor: '#99000022',
borderColor: '#990000',
pointHoverBackgroundColor: '#fff',
borderWidth: 2,
data: data_array,
}
]
}
line_chart_1_opt = {
tooltips: {
enabled: false
},
maintainAspectRatio: false,
legend: {
display: false,
},
scales: {
xAxes: [
{
gridLines: {
drawOnChartArea: false,
},
type: 'linear'
}],
yAxes: [
{
ticks: {
beginAtZero: true,
maxTicksLimit: 5,
stepSize: Math.ceil(250 / 5)
},
}],
},
elements: {
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 4,
hoverBorderWidth: 3,
},
},
title: {
text: 'chart_one'
},
options: {
plugins: {
labels: false
}
}
};
Chart.pluginService.register({
afterDraw: function (chart, easing) {
var margin = 46;
var margin_end = 5;
if (chart.config.options.title.text == 'chart_one') {
var diff = chart.scales['x-axis-0'].end - chart.scales['x-axis-0'].start;
var val = b_amount - chart.scales['x-axis-0'].start;
const ctx = chart.ctx;
const x = (val / diff) * (chart.width - (margin + margin_end)) + margin;
const topY = chart.scales['y-axis-0'].top;
const bottomY = chart.scales['y-axis-0'].bottom;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#ff0000';
ctx.stroke();
}
<Line data={line_chart_1} options={line_chart_1_opt} height={200} />
Related
I created a bubble chart with chart.JS 2.0 (risk matrix). I would now like to color the background with a green circle centered on the bottom left of the chart which would become red when expanding to the top right.
I managed to create the circle on the background which generates the following chart :
I would now like to have the circle centered on the bottom left but I am struggling to deal with the coordinates.
Chart.pluginService.register({
beforeDraw: function(chart, easing) {
if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
var helpers = Chart.helpers;
var ctx = chart.chart.ctx;
var chartArea = chart.chartArea;
// {left: 45.073828125, top: 34.4, right: 588, bottom: 538.2}
ctx.save();
var canevas = document.querySelector("canvas");
var contexte = canevas.getContext('2d');
X = chartArea.right;
Y = chartArea.bottom;
leftoffset = chartArea.left;
topoffset = chartArea.top;
// var gradient = ctx.createLinearGradient(0, 70, 70, 0);
var gradient = ctx.createRadialGradient(X / 1.34, Y / 1.412, X / 8, X / 4 * 3, Y / 2, X / 3);
gradient.addColorStop(0, "green");
gradient.addColorStop(0.5, "orange");
gradient.addColorStop(1, "red");
ctx.fillStyle = gradient;
ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
}
}
});
var myBubbleChart = new Chart(document.getElementById("bubble-chart"), {
type: 'bubble',
data: {
labels: "Africa",
datasets: [{
idu: 29,
label: ["Hurricane"],
backgroundColor: "#398B93",
data: [{
x: 4,
y: 1,
r: 15
}]
},
{
idu: 30,
label: ["Flooding"],
backgroundColor: "#398B93",
data: [{
x: 5,
y: 4,
r: 15
}]
},
{
idu: 31,
label: ["Cyber-attack"],
backgroundColor: "#398B93",
data: [{
x: 1,
y: 4,
r: 15
}]
},
]
},
options: {
chartArea: {
backgroundColor: 'linear-gradient(0.25turn, #3f87a6, #ebf8e1, #f69d3c)'
},
title: {
display: true,
text: 'Risk matrix'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: "Likelihood"
},
ticks: {
min: 0, // Controls where axis starts
max: 6, // Controls where axis finishes
stepSize: 1,
display: true,
callback: function(tick) {
return (tick !== 0) && (tick !== 6) ? tick : '';
}
},
gridLines: {
display: true,
drawBorder: false,
lineWidth: 1, // Width of line,
offsetGridLines: true,
color: '#EBEEEE',
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: "Impact"
},
ticks: {
min: 0, // Controls where axis starts
max: 6, // Controls where axis finishes
stepSize: 1,
display: true,
callback: function(tick) {
return (tick !== 0) && (tick !== 6) ? tick : '';
}
},
gridLines: {
display: true,
drawBorder: false,
offsetGridLines: true,
color: '#ebeeee',
}
}]
},
legend: {
display: false,
labels: {
fontColor: 'rgb(255, 99, 132)'
}
},
jitter: true,
}
});
#bubble-chart {
max-width: 90%;
max-height: 90%;
}
<canvas id="bubble-chart" width="800" height="800"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
Thanks a lot
I'm using Charts.js library to display a line graph from data which is constantly updated. Is there a way to display only the final point value at all times? I want it to do this to monitor the added values at all times.
javascript code:
var config2 = {
type: 'line',
data: {
labels: 0,
datasets: [{
label: "No selection",
lineTension: 0,
borderColor: "rgba(222, 44, 31)",
pointBackgroundColor: "#fff675",
fill: false,
data: 0,
}
]
},
options: {
responsive: true,
title: {
display: false,
text: 'Chart.js Time Point Data'
},
scales: {
x: {
type: 'time',
display: true,
scaleLabel: {
display: true,
labelString: 'Date'
},
ticks: {
major: {
enabled: true
},
fontStyle: function(context) {
return context.tick && context.tick.major ? 'bold' : undefined;
},
fontColor: function(context) {
return context.tick && context.tick.major ? '#FF0000' : undefined;
}
}
},
y: {
display: true,
scaleLabel: {
display: true,
labelString: 'value'
}
}
}
}
};
Each time, a new value is available, you can simply remove outdated labels and dataset.data values once a certain limit is reached. This can be done using Array.shift(), which removes the first element from an array. Once these array are updated, you need to invoke chart.update().
var maxValues = 4;
setInterval(() => {
chart.data.labels.push(new Date());
chart.data.datasets[0].data.push(Math.floor((Math.random() * 20) + 1));
if (chart.data.labels.length > maxValues) {
chart.data.labels.shift();
chart.data.datasets[0].data.shift();
}
chart.update();
}, 1000);
For displaying the value on the last added data point, you can use the Plugin Core API. It offers different hooks that may be used for executing custom code. In below runnable code snippet, I use the afterDraw hook to draw text directly on the canvas.
var chart = new Chart('chart', {
type: "line",
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var iLastValue = chart.data.labels.length - 1;
var lastValue = chart.data.datasets[0].data[iLastValue];
var x = xAxis.getPixelForValue(chart.data.labels[iLastValue]);
var y = yAxis.getPixelForValue(lastValue);
ctx.save();
ctx.textAlign = 'center';
ctx.font = '14px Arial';
ctx.fillStyle = "red";
ctx.fillText('Value: ' + lastValue, x, y - 15);
ctx.restore();
}
}],
responsive: true,
maintainAspectRatio: false,
data: {
labels: [],
datasets: [{
label: "Data",
data: [],
fill: false,
lineTension: 0,
backgroundColor: "white",
borderColor: "red",
}]
},
options: {
layout: {
padding: {
right: 50
}
},
scales: {
xAxes: [{
type: 'time',
ticks: {
source: 'auto'
},
time: {
unit: 'second',
displayFormats: {
second: 'mm:ss'
},
tooltipFormat: 'mm:ss'
},
}],
yAxes: [{
ticks: {
min: 0,
max: 20,
stepSize: 5
}
}]
}
}
});
var maxValues = 4;
setInterval(() => {
chart.data.labels.push(new Date());
chart.data.datasets[0].data.push(Math.floor((Math.random() * 20) + 1));
if (chart.data.labels.length > maxValues) {
chart.data.labels.shift();
chart.data.datasets[0].data.shift();
}
chart.update();
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="chart" height="90"></canvas>
How to set line height only until points? I have used 'gridLines: display:false' but it hides all lines. Here on image below how it should be
It's not a native option in Chart.js but you can implement it yourself via plugin. See the annotations in the below code.
new Chart(document.getElementById('chart'), {
type: 'line',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [{
label: 'series 1',
data: [0, 2, 4, 3, 1, 0]
}]
},
options: {
maintainAspectRatio: false,
scales: {
xAxes: [{
gridLines: {
display: false, // must be false since we're going to draw our own 'gridlines'!
color: 'rgba(255, 0, 0, .2)', // can still set the colour.
lineWidth: 5 // can still set the width.
}
}],
yAxes: [{
gridLines: {
display: false
},
ticks: {
beginAtZero: true
}
}]
}
},
plugins: [{ // this is the magical bit :)
afterRender: function(c, options) {
let meta = c.getDatasetMeta(0),
max;
c.ctx.save();
c.ctx.strokeStyle = c.config.options.scales.xAxes[0].gridLines.color;
c.ctx.lineWidth = c.config.options.scales.xAxes[0].gridLines.lineWidth;
c.ctx.beginPath();
meta.data.forEach(function(e) {
if (max == undefined || c.config.data.datasets[0].data[e._index] > max) {
max = c.config.data.datasets[0].data[e._index];
}
c.ctx.moveTo(e._model.x, meta.dataset._scale.bottom);
c.ctx.lineTo(e._model.x, e._model.y);
});
c.ctx.textBaseline = 'top';
c.ctx.textAlign = 'right';
c.ctx.fillStyle = 'black';
c.ctx.fillText('Max value: ' + max, c.width - 10, 10);
c.ctx.stroke();
c.ctx.restore();
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<canvas id="chart"></canvas>
I am working on chartjs ( version 2.7.2). I want to create a bar chart having a border radius ( 'barradius' as per the chartjs option).
Something Like this:
I have set value for barradius:4 but it is not working.
HTML:
<canvas id="myChart" width="400" height="200"></canvas>
Javascript:
var canvas = document.getElementById('myChart');
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 2,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [65, 59, 20, 81, 56, 55, 40],
}
]
};
var option = {
title: {
display: false,
},
tooltips: {
intersect: false,
mode: 'nearest',
xPadding: 10,
yPadding: 10,
caretPadding: 10
},
legend: {
display: false
},
responsive: true,
maintainAspectRatio: false,
barRadius: 4,
scales: {
xAxes: [{
display: false,
gridLines: false,
stacked: true
}],
yAxes: [{
display: false,
stacked: true,
gridLines: false
}]
},
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 0
}
}
};
var myBarChart = Chart.Bar(canvas, {
data: data,
options: option
});
var myBarChart = Chart.Bar(canvas, {
data: data,
options: option
});
Also check from here https://jsfiddle.net/anadi/mag91f8k/1006/
As far as i saw in similar problems the solution should be to extend the Chart.types.Bar.extend
https://jsfiddle.net/hyacinthe/t8khnL4q/
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function (data) {
Chart.types.Bar.prototype.initialize.apply(this, arguments);
if (this.options.curvature !== undefined && this.options.curvature <= 1) {
var rectangleDraw = this.datasets[0].bars[0].draw;
var self = this;
var radius = this.datasets[0].bars[0].width * this.options.curvature * 0.2;
// override the rectangle draw with ours
this.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
bar.draw = function () {
// draw the original bar a little down (so that our curve brings it to its original position)
var y = bar.y;
// the min is required so animation does not start from below the axes
bar.y = Math.min(bar.y + radius, self.scale.endPoint - 1);
// adjust the bar radius depending on how much of a curve we can draw
var barRadius = (bar.y - y);
rectangleDraw.apply(bar, arguments);
// draw a rounded rectangle on top
Chart.helpers.drawRoundedRectangle(self.chart.ctx, bar.x - bar.width / 2, bar.y - barRadius + 1, bar.width, bar.height, barRadius);
ctx.fill();
// restore the y value
bar.y = y;
}
})
})
}
}
});
The credit of this answer goes to #potatopeelings.
I have drawn a Chart using Chart.js. It does not automatically draw an end line at the end(right side) of the Chart:
I have used plugin code to hide the overlaying vertical lines which are drawn by Chartjs automatically. I could not find another way to hide those. Here is the code which describes the Chart.
function getHydrationOverviewChart(elementID) {
Chart.plugins.register({
beforeDraw: function(chart) {
var ctx = chart.chart.ctx,
x_axis = chart.scales['x-axis-0'],
topY = chart.scales['y-axis-0'].top,
bottomY = chart.scales['y-axis-0'].bottom;
x_axis.options.gridLines.display = false;
x_axis.ticks.forEach(function(label, index) {
var x = x_axis.getPixelForValue(label);
ctx.save();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.stroke();
ctx.restore();
});
}
});
var options = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5"],
datasets: [
{
borderWidth: 2,
borderColor: "#5d5d5d",
pointBorderColor: "#5d5d5d",
pointBackgroundColor: "#5d5d5d",
pointBorderWidth: 5,
type: 'line',
data: [26, 26, 33, 28, 30],
fill: false,
lineTension: 0
},
{
borderWidth: 3,
pointBorderColor: "#b8b8b8",
pointBackgroundColor: "#b8b8b8",
pointBorderWidth: 10,
type: 'line',
data: [26, 26, 29, 28, 29],
fill: false,
lineTension: 0
},
{
data: [0, 0, 0, 0, 0],
fill: false,
lineTension: 0
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
hover: {mode: null},
legend: {
display: false
},
tooltips: {enabled: false},
hover: {mode: null},
scales: {
xAxes: [{
gridLines: {
// drawBorder: false,
},
}],
yAxes: [{
display: false,
ticks: {
suggestedMin: 0,
max: 60,
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById(elementID).getContext('2d');
new Chart(ctx, options);
}
Does anybody know how I can add this vertical endline?
This can be accomplished using the following chart plugin :
Chart.plugins.register({
beforeDraw: function(chart) {
var ctx = chart.chart.ctx,
x_axis = chart.scales['x-axis-0'],
topY = chart.scales['y-axis-0'].top,
bottomY = chart.scales['y-axis-0'].bottom;
x_axis.options.gridLines.display = false;
for (i = 0; i <= x_axis.ticks.length; i++) {
var x = i === x_axis.ticks.length ?
x_axis.right :
x_axis.getPixelForValue(x_axis.ticks[i]);
ctx.save();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.stroke();
ctx.restore();
}
}
});
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
Chart.plugins.register({
beforeDraw: function(chart) {
var ctx = chart.chart.ctx,
x_axis = chart.scales['x-axis-0'],
topY = chart.scales['y-axis-0'].top,
bottomY = chart.scales['y-axis-0'].bottom;
x_axis.options.gridLines.display = false;
for (i = 0; i <= x_axis.ticks.length; i++) {
var x = i === x_axis.ticks.length ?
x_axis.right :
x_axis.getPixelForValue(x_axis.ticks[i]);
ctx.save();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.stroke();
ctx.restore();
}
}
});
var options = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5"],
datasets: [{
borderWidth: 2,
borderColor: "#5d5d5d",
pointBorderColor: "#5d5d5d",
pointBackgroundColor: "#5d5d5d",
pointBorderWidth: 5,
type: 'line',
data: [26, 26, 33, 28, 30],
fill: false,
lineTension: 0
}, {
borderWidth: 3,
pointBorderColor: "#b8b8b8",
pointBackgroundColor: "#b8b8b8",
pointBorderWidth: 10,
type: 'line',
data: [26, 26, 29, 28, 29],
fill: false,
lineTension: 0
}, {
data: [0, 0, 0, 0, 0],
fill: false,
lineTension: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
hover: {
mode: null
},
legend: {
display: false
},
tooltips: {
enabled: false
},
hover: {
mode: null
},
scales: {
xAxes: [{
gridLines: {
// drawBorder: false,
},
}],
yAxes: [{
display: false,
ticks: {
suggestedMin: 0,
max: 60,
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById('canvas').getContext('2d');
new Chart(ctx, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas" height="400"></canvas>