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.
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 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} />
Please, I need some help to make some suspense in showing poll final results in my chartjs canvas.
The bars have the same duration speed relative to their value, how to set the duration speed to each bar in the chart?
1st step 4 bars at 36%
2nd step 3 bars at 48%
Final Step 1 bar at 60%
This is my chart
This my chartjs code
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
animation:{
duration : 6000,
},
scales: {
yAxes: [{
gridLines: {
show: false,
display:false,
drawBorder: false,
lineWidth: 0,
drawOnChartArea: false
},
ticks: {
beginAtZero: true,
display: false,
maxTicksLimit: 5,
}
}],
xAxes: [{
gridLines: {
show: false,
lineWidth: 0,
display:false,
drawBorder: false,
drawOnChartArea: false,
},
ticks: {
show: false,
display:false,
}
}]
}
}
});
I don't know if there is a better way to do it, but the simplest thing I could think of is to update the dataset according to our needs.
Initially, we can keep all data elements equal and then gradually change them as we want.
Here is a simple solution that I managed to code link.
var canvas = document.getElementById('myChart');
var dataPoints = [65, 59, 30, 81, 56, 55, 40];
var chartData = [];
chartData.length = dataPoints.length;
chartData.fill(nthSmallest(dataPoints, 1));
var doNotOverwrite = [dataPoints.indexOf(chartData[0])];
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: chartData,
}
]
};
var myBarChart = Chart.Bar(canvas,{
data:data,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
suggestedMax: Math.max(...dataPoints)
}
}]
}
}
});
var index = 0;
var interval = setInterval(()=> {
index++;
var num = nthSmallest(dataPoints, index);
appendArray(num);
doNotOverwrite.push(dataPoints.indexOf(chartData[0]));
myBarChart.update();
if(index == dataPoints.length) {
clearInterval(interval);
}
}, 1000);
function appendArray(num) {
for(let i = 0; i< chartData.length; i++) {
if(!doNotOverwrite.includes(i)) {
chartData[i] = num;
}
}
}
function nthSmallest(numbers, n) {
numbers = JSON.parse(JSON.stringify(numbers));
var sorted = numbers.sort(function (a, b) {
return b - a;
});
return sorted[sorted.length - n];
}
I wrote it in a hurry, so there might be some issues with the code. (Array with repetitive elements will not work as I am using index).
You will also need to update your options for it to work properly.
I know it is not the prettiest solution, but hey it works. :)
I'm using ChartJS V2 to create a chart. Chartjs V2 supports the fill color feature. But I would like to fill overlap area with different color.
Please see screenshot below. I have two line. A represents overlap area for two lines.
I would like to fill with 3 different color for 2 lines.
When the Line1 and Line2 overlaps, fill color should be A
If Line1 does not overlap Line2, fill color should be B
If Line2 does not overlap Line1, fill color should be C
I added a fiddle for this.
See Fiddle http://jsfiddle.net/qcs1t9ag/
Thanks!
var lineChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [50, 85, 56, 50, 60, 70, 80],
yAxisID: "y-axis-1",
borderColor: "#0ad4e6"
}, {
label: "My Second dataset",
data: [35, 45, 75, 40, 55, 50, 62],
yAxisID: "y-axis-2",
borderColor: "#f6c63e"
}]
};
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = Chart.Line(ctx, {
data: lineChartData,
options: {
responsive: true,
hoverMode: 'label',
stacked: false,
title: {
display: false,
text: 'Chart.js Line Chart - Multi Axis'
},
animation: {
duration: 0
},
legend: {
display: false,
position: 'top',
},
scales: {
xAxes: [{
display: true,
gridLines: {
offsetGridLines: false
}
}],
yAxes: [{
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "left",
id: "y-axis-1",
scaleLabel: {
display: true,
labelString: "Cost"
}
}, {
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "right",
id: "y-axis-2",
scaleLabel: {
display: true,
labelString: "Students",
},
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
});
JueDoe, Here's an example below of how you could do this.
Fiddle: Charts intersection example
var ORDER_STATS = {
"2016": [10, 181, 194, -56, 130, 181, 179, 189, 30, 60, 193, 154],
"2015": [124, -50, 152, 187, 10, 164, 129, -16, 115, 119, 129, 171],
"2014": [-90, 80, 30, 59, 100, -30, 60, 116, 191, 181, -60, 106]
};
var colors = ['206,191,26', '119,206,26', '26,200,206', '236,124,98', '206,26,140', '26,77,206'];
// Definning X
var ordersChartData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: []
}
Object.keys(ORDER_STATS).forEach(function(key) {
color = colors.shift();
ordersChartData.datasets.push({
label: key,
lineTension: 0,
type: 'line',
backgroundColor: "rgba(" + color + ",0.1)",
borderColor: "rgba(" + color + ",1)",
borderWidth: 2,
pointBackgroundColor: "rgba(" + color + ",1)",
pointBorderColor: "#fff",
pointBorderWidth: 1,
pointRadius: 4,
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(" + color + ",1)",
pointHoverBorderWidth: 1,
data: ORDER_STATS[key]
});
});
var ctx = document.getElementById("myChart").getContext("2d");
Chart.defaults.global.defaultFontColor = 'grey';
Chart.defaults.global.defaultFontFamily = "Tahoma";
Chart.defaults.global.defaultFontSize = 11;
Chart.defaults.global.defaultFontStyle = 'normal';
var myChart = new Chart(ctx, {
type: 'line',
data: ordersChartData,
defaultFontSize: 11,
options: {
responsive: true,
title: {
display: true,
text: 'Intersection realization',
fontColor: "#444",
fontFamily: 'Tahoma',
padding: 0
},
legend: {
display: true,
labels: {
fontColor: 'grey',
usePointStyle: true
}
},
tooltips: {
mode: "index",
intersect: true,
position: 'nearest',
bodySpacing: 4
}
}
});
Chart.plugins.register({
afterDatasetsDraw: function(chartInstance, easing) {
var intersects = findIntersects(ORDER_STATS['2015'], ORDER_STATS['2014']);
var context = chartInstance.chart.ctx;
var Y = chartInstance.scales['y-axis-0'];
var X = chartInstance.scales['x-axis-0'];
zeroPointY = Y.top + ((Y.bottom - Y.top) / (Y.ticks.length - 1) * Y.zeroLineIndex);
zeroPointX = Y.right;
yScale = (Y.bottom - Y.top) / (Y.end - Y.start);
xScale = (X.right - X.left) / (X.ticks.length - 1);
intersects.forEach(function(result, idx) {
context.fillStyle = 'red';
context.beginPath();
context.arc((result.x * xScale) + zeroPointX, (Y.end - Y.start) - (result.y * yScale) - ((Y.end - Y.start) - zeroPointY), 3, 0, 2 * Math.PI, true);
context.fill();
});
}
});
function findIntersects(line1, line2) {
var intersects = [];
line1.forEach(function(val, idx) {
var line1StartX = idx;
var line1StartY = line1[idx];
var line1EndX = idx + 1;
var line1EndY = line1[idx + 1];
var line2StartX = idx;
var line2StartY = line2[idx];
var line2EndX = idx + 1;
var line2EndY = line2[idx + 1];
result = checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY);
if (result.onLine1 && result.onLine2) {
intersects.push(result);
}
});
return intersects;
}
function checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
// if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
var denominator, a, b, numerator1, numerator2, result = {
x: null,
y: null,
onLine1: false,
onLine2: false
};
denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
if (denominator == 0) {
return result;
}
a = line1StartY - line2StartY;
b = line1StartX - line2StartX;
numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
a = numerator1 / denominator;
b = numerator2 / denominator;
// if we cast these lines infinitely in both directions, they intersect here:
result.x = line1StartX + (a * (line1EndX - line1StartX));
result.y = line1StartY + (a * (line1EndY - line1StartY));
/*
// it is worth noting that this should be the same as:
x = line2StartX + (b * (line2EndX - line2StartX));
y = line2StartX + (b * (line2EndY - line2StartY));
*/
// if line1 is a segment and line2 is infinite, they intersect if:
if (a > 0 && a < 1) {
result.onLine1 = true;
}
// if line2 is a segment and line1 is infinite, they intersect if:
if (b > 0 && b < 1) {
result.onLine2 = true;
}
// if line1 and line2 are segments, they intersect if both of the above are true
return result;
};
If it is not what you want, I recommend you draw the third line with the difference between the first and second line... or draw another graph with only the third line (calculate the difference between line A and line B).
Fiddle: Third Line
Official documentation.
Here (official) you have several graph examples.
I'm testing with Chart.js and trying to remove the grid. My code:
function grafica(){
var chartData = {
labels: [" ", " ", " "],
datasets: [
{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",//marges
data: [30, 40, 45]
}, {
fillColor: "rgb(210,27,71)",
strokeColor: "rgb(210,27,71)",//marges
data: [56, 55, 40]
}, {
fillColor: "rgba(210,27,71,0)",
strokeColor: "rgba(210,27,71,0)",//marges
data: [0, 0, 0]
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor;
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
}
});
}
How can I do it? I tried some things like add "ctx.gridLines = false;" and "ctx.ticks = false;" but at the moment anything works.
Edit:
I did some changes following your instructions but I don't know why anything work.
The version I'm using is 2.0.0-alpha
On v3 (Updated docs) is changed to
options: {
scales: {
x: {
grid: {
display: false
}
},
y: {
grid: {
display: false
}
}
},
}
I am now using version 2.0Alpha, same as you.
Updated Documentation Link
Below is an example for a simple bar chart without grid lines.
You need to set the 'gridLines' key on the y and xAxis keys of the options object.
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
var barChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: 'Dataset 1',
backgroundColor: "rgba(151,187,205,0.5)",
data: [100,99,98,97,96,95,94]
}]
};
window.myBar = new Chart(ctx).Bar({
data: barChartData,
options: {
responsive: true,
scales: {
xAxes: [{
gridLines: {
show: true
}
}],
yAxes: [{
gridLines: {
show: false
}
}]
}
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0-alpha/Chart.min.js"></script>
<div>
<canvas id="canvas"></canvas>
</div>
Try it with:
xAxis: {
gridLineWidth: 0
},
yAxis: {
gridLineWidth: 0,
minorTickInterval: null
}
Add this to the chart data,