score:0
checkout chartjs-top-round-bar a usefull
you just need to
import 'chartjs-top-round-bar';
...
new chart('mychart',
{
options: {
barroundness: 0.3
}
}
score:1
got this working in angular 11 and charts.js version 2.9.4 (might work in other versions too)
add this at the very end of your .component.ts file after export class { .. }
chart['elements'].rectangle.prototype.draw = function() {
let ctx = this._chart.ctx;
let view = this._view;
//////////////////// edit this to change how rounded the edges are /////////////////////
let borderradius = 10;
let left = view.x - view.width / 2;
let right = view.x + view.width / 2;
let top = view.y;
let bottom = view.base;
ctx.beginpath();
ctx.fillstyle = view.backgroundcolor;
ctx.strokestyle = view.bordercolor;
ctx.linewidth = view.borderwidth;
let barcorners = [
[left, bottom],
[left, top],
[right, top],
[right, bottom]
];
//start in bottom-left
ctx.moveto(barcorners[0][0], barcorners[0][1]);
for (let i = 1; i < 4; i++) {
let x = barcorners[1][0];
let y = barcorners[1][1];
let width = barcorners[2][0] - barcorners[1][0];
let height = barcorners[0][1] - barcorners[1][1];
//fix radius being too big for small values
if(borderradius > width/2){
borderradius = width/2;
}
if(borderradius > height/2){
borderradius = height/2;
}
// draw the lines that will be filled - replacing lineto with quadraticcurveto causes more edges to become rounded
ctx.moveto(x + borderradius, y);
ctx.lineto(x + width - borderradius, y);
ctx.quadraticcurveto(x + width, y, x + width, y + borderradius);
ctx.lineto(x + width, y + height - borderradius);
ctx.lineto(x + width, y + height, x + width - borderradius, y + height);
ctx.lineto(x + borderradius, y + height);
ctx.lineto(x, y + height, x, y + height - borderradius);
ctx.lineto(x, y + borderradius);
ctx.quadraticcurveto(x, y, x + borderradius, y);
}
//fill the lines
ctx.fill();
};
example ngoninit method:
ngoninit() {
console.log("asdf entering getchart");
this.canvas = document.getelementbyid('numberofsessionschart');
this.ctx = this.canvas.getcontext('2d');
this.mychart = new chart(this.ctx, {
type: 'bar',
data: {
labels: ['jan 20', 'feb 20', 'mar 20', 'apr 20', 'may 20', 'jun 20', 'jul 20', 'aug 20', 'sept 20'],
datasets: [{
label: 'vvals',
backgroundcolor: 'blue',
data: [0, 50, 20, 30, 40, 50, 60, 70, 80, 90, 100],
}]
},
options: {
devicepixelratio: 2.2,
//tooltips are the things that appear when you hover over the data that show the counts.
//for some reason we can't choose where the tooltip is oriented.
tooltips: {
enabled: false
},
onclick: (e) => {
console.log("asdf entering on click");
},
legend: {
display: true,
position: 'right',
reverse: true,
labels: {
fontcolor: 'black',
fontsize: 15,
padding: 20,
usepointstyle: true,
//width of circles in legend
boxwidth: 9
}
},
scales: {
xaxes: [{
ticks: {
padding: 10,
fontsize: 13,
fontfamily: 'roboto',
fontcolor: 'black',
beginatzero: true
},
gridlines: {
tickmarklength: 0,
color: '#9da0a2',
drawonchartarea: false,
},
}],
yaxes: [{
ticks: {
padding: 10,
fontsize: 13,
fontfamily: 'roboto',
fontcolor: 'black',
beginatzero: true,
precision:0
},
gridlines: {
tickmarklength: 0,
color: '#9da0a2',
drawonchartarea: false,
},
}],
},
responsive: false,
}
});
}
}
score:2
also worth a mention is this solution which takes you 30 seconds to implement:
https://github.com/jedtrow/chart.js-rounded-bar-charts
download and put the .js file into your projects folder, load it and use
var options = {
cornerradius: 20,
};
to get rounded bars.
credits: https://github.com/jedtrow
score:3
solution by @jordanwillis doesn't work with chart.js version after 2.8.0.
to make it work just add following code before drawroundedtoprectangle
definition
chart.helpers.merge(chart.defaults.global, {
datasets: {
roundedbar: {
categorypercentage: 0.8,
barpercentage: 0.9
}
}
});
score:8
the following only customizes the chart.elements.rectangle.prototype.draw
- no need to create an entirely new chart type.
other pros:
- it works well with both vertical & horizontal bar charts
- it works well with both vertical & horizontal stacked bar charts - it only rounds the last box in the series
noted issue: because this only rounds the box in the last dataset, if the value of the datapoint in the last dataset is < either of the previous data points, the visual top-most box will not be rounded. however, if the last data point is negative and the lowest value, it will round that box on the bottom corners.
credit: original code belongs to https://github.com/uffo. code below and linked fiddle demonstrate increasing positive values in each dataset for each stack, and also modifies some of the default radius options.
/**customize the rectangle.prototype draw method**/
chart.elements.rectangle.prototype.draw = function() {
var ctx = this._chart.ctx;
var vm = this._view;
var left, right, top, bottom, signx, signy, borderskipped, radius;
var borderwidth = vm.borderwidth;
// if radius is less than 0 or is large enough to cause drawing errors a max
// radius is imposed. if cornerradius is not defined set it to 0.
var cornerradius = this._chart.config.options.cornerradius;
var fullcornerradius = this._chart.config.options.fullcornerradius;
var stackedrounded = this._chart.config.options.stackedrounded;
var typeofchart = this._chart.config.type;
if (cornerradius < 0) {
cornerradius = 0;
}
if (typeof cornerradius == 'undefined') {
cornerradius = 0;
}
if (typeof fullcornerradius == 'undefined') {
fullcornerradius = false;
}
if (typeof stackedrounded == 'undefined') {
stackedrounded = false;
}
if (!vm.horizontal) {
// bar
left = vm.x - vm.width / 2;
right = vm.x + vm.width / 2;
top = vm.y;
bottom = vm.base;
signx = 1;
signy = bottom > top ? 1 : -1;
borderskipped = vm.borderskipped || 'bottom';
} else {
// horizontal bar
left = vm.base;
right = vm.x;
top = vm.y - vm.height / 2;
bottom = vm.y + vm.height / 2;
signx = right > left ? 1 : -1;
signy = 1;
borderskipped = vm.borderskipped || 'left';
}
// canvas doesn't allow us to stroke inside the width so we can
// adjust the sizes to fit if we're setting a stroke on the line
if (borderwidth) {
// borderwidth shold be less than bar width and bar height.
var barsize = math.min(math.abs(left - right), math.abs(top - bottom));
borderwidth = borderwidth > barsize ? barsize : borderwidth;
var halfstroke = borderwidth / 2;
// adjust borderwidth when bar top position is near vm.base(zero).
var borderleft = left + (borderskipped !== 'left' ? halfstroke * signx : 0);
var borderright = right + (borderskipped !== 'right' ? -halfstroke * signx : 0);
var bordertop = top + (borderskipped !== 'top' ? halfstroke * signy : 0);
var borderbottom = bottom + (borderskipped !== 'bottom' ? -halfstroke * signy : 0);
// not become a vertical line?
if (borderleft !== borderright) {
top = bordertop;
bottom = borderbottom;
}
// not become a horizontal line?
if (bordertop !== borderbottom) {
left = borderleft;
right = borderright;
}
}
ctx.beginpath();
ctx.fillstyle = vm.backgroundcolor;
ctx.strokestyle = vm.bordercolor;
ctx.linewidth = borderwidth;
// corner points, from bottom-left to bottom-right clockwise
// | 1 2 |
// | 0 3 |
var corners = [
[left, bottom],
[left, top],
[right, top],
[right, bottom]
];
// find first (starting) corner with fallback to 'bottom'
var borders = ['bottom', 'left', 'top', 'right'];
var startcorner = borders.indexof(borderskipped, 0);
if (startcorner === -1) {
startcorner = 0;
}
function cornerat(index) {
return corners[(startcorner + index) % 4];
}
// draw rectangle from 'startcorner'
var corner = cornerat(0);
ctx.moveto(corner[0], corner[1]);
var nextcornerid, nextcorner, width, height, x, y;
for (var i = 1; i < 4; i++) {
corner = cornerat(i);
nextcornerid = i + 1;
if (nextcornerid == 4) {
nextcornerid = 0
}
nextcorner = cornerat(nextcornerid);
width = corners[2][0] - corners[1][0];
height = corners[0][1] - corners[1][1];
x = corners[1][0];
y = corners[1][1];
var radius = cornerradius;
// fix radius being too large
if (radius > math.abs(height) / 2) {
radius = math.floor(math.abs(height) / 2);
}
if (radius > math.abs(width) / 2) {
radius = math.floor(math.abs(width) / 2);
}
var x_tl, x_tr, y_tl, y_tr, x_bl, x_br, y_bl, y_br;
if (height < 0) {
// negative values in a standard bar chart
x_tl = x;
x_tr = x + width;
y_tl = y + height;
y_tr = y + height;
x_bl = x;
x_br = x + width;
y_bl = y;
y_br = y;
// draw
ctx.moveto(x_bl + radius, y_bl);
ctx.lineto(x_br - radius, y_br);
// bottom right
ctx.quadraticcurveto(x_br, y_br, x_br, y_br - radius);
ctx.lineto(x_tr, y_tr + radius);
// top right
fullcornerradius ? ctx.quadraticcurveto(x_tr, y_tr, x_tr - radius, y_tr) : ctx.lineto(x_tr, y_tr, x_tr - radius, y_tr);
ctx.lineto(x_tl + radius, y_tl);
// top left
fullcornerradius ? ctx.quadraticcurveto(x_tl, y_tl, x_tl, y_tl + radius) : ctx.lineto(x_tl, y_tl, x_tl, y_tl + radius);
ctx.lineto(x_bl, y_bl - radius);
// bottom left
ctx.quadraticcurveto(x_bl, y_bl, x_bl + radius, y_bl);
} else if (width < 0) {
// negative values in a horizontal bar chart
x_tl = x + width;
x_tr = x;
y_tl = y;
y_tr = y;
x_bl = x + width;
x_br = x;
y_bl = y + height;
y_br = y + height;
// draw
ctx.moveto(x_bl + radius, y_bl);
ctx.lineto(x_br - radius, y_br);
// bottom right corner
fullcornerradius ? ctx.quadraticcurveto(x_br, y_br, x_br, y_br - radius) : ctx.lineto(x_br, y_br, x_br, y_br - radius);
ctx.lineto(x_tr, y_tr + radius);
// top right corner
fullcornerradius ? ctx.quadraticcurveto(x_tr, y_tr, x_tr - radius, y_tr) : ctx.lineto(x_tr, y_tr, x_tr - radius, y_tr);
ctx.lineto(x_tl + radius, y_tl);
// top left corner
ctx.quadraticcurveto(x_tl, y_tl, x_tl, y_tl + radius);
ctx.lineto(x_bl, y_bl - radius);
// bttom left corner
ctx.quadraticcurveto(x_bl, y_bl, x_bl + radius, y_bl);
} else {
var lastvisible = 0;
for (var findlast = 0, findlastto = this._chart.data.datasets.length; findlast < findlastto; findlast++) {
if (!this._chart.getdatasetmeta(findlast).hidden) {
lastvisible = findlast;
}
}
var rounded = this._datasetindex === lastvisible;
if (rounded) {
//positive value
ctx.moveto(x + radius, y);
ctx.lineto(x + width - radius, y);
// top right
ctx.quadraticcurveto(x + width, y, x + width, y + radius);
ctx.lineto(x + width, y + height - radius);
// bottom right
if (fullcornerradius || typeofchart == 'horizontalbar')
ctx.quadraticcurveto(x + width, y + height, x + width - radius, y + height);
else
ctx.lineto(x + width, y + height, x + width - radius, y + height);
ctx.lineto(x + radius, y + height);
// bottom left
if (fullcornerradius)
ctx.quadraticcurveto(x, y + height, x, y + height - radius);
else
ctx.lineto(x, y + height, x, y + height - radius);
ctx.lineto(x, y + radius);
// top left
if (fullcornerradius || typeofchart == 'bar')
ctx.quadraticcurveto(x, y, x + radius, y);
else
ctx.lineto(x, y, x + radius, y);
}else {
ctx.moveto(x, y);
ctx.lineto(x + width, y);
ctx.lineto(x + width, y + height);
ctx.lineto(x, y + height);
ctx.lineto(x, y);
}
}
}
ctx.fill();
if (borderwidth) {
ctx.stroke();
}
};
/**chart data**/
var data = {
labels: ["red", "blue", "yellow", "green", "purple", "orange"],
datasets: [{
label: 'data 0',
data: [12, 19, 3, 5, 2, 3],
backgroundcolor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderwidth: 0
}, {
label: 'data 1',
data: [20, 24, 10, 15, 12, 13],
backgroundcolor: [
'rgba(255, 159, 64, 1)',
'rgba(255, 99, 132, 1)',
'rgba(255, 206, 86, 1)',
'rgba(54, 162, 235, 1)',
'rgba(153, 102, 255, 1)',
'rgba(75, 192, 192, 1)'
],
borderwidth: 0
}, {
label: 'data 2',
data: [20, 30, 30, 20, 14, 20],
backgroundcolor: [
'rgba(75, 192, 192, 1)',
'rgba(255, 159, 64, 1)',
'rgba(255, 99, 132, 1)',
'rgba(255, 206, 86, 1)',
'rgba(54, 162, 235, 1)',
'rgba(153, 102, 255, 1)'
],
borderwidth: 0
}]
};
/**chart options - radius options are here**/
var options = {
//border radius; default: 0; if a negative value is passed, it will overwrite to 0;
cornerradius: 10,
//default: false; if true, this would round all corners of final box;
fullcornerradius: false,
//default: false; if true, this rounds each box in the stack instead of only final box;
stackedrounded: false,
elements: {
point: {
radius: 25,
hoverradius: 35,
pointstyle: 'rectrounded',
}
},
scales: {
yaxes: [{
ticks: {
beginatzero: true
},
stacked: true,
radius: 25
}],
xaxes: [{
ticks: {
beginatzero: true
},
stacked: true,
}]
}
};
/**generate chart**/
var ctxbar = document.getelementbyid("mychart");
var mybarchart = new chart(ctxbar, {
type: 'bar',
data: data,
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/chart.js/2.7.1/chart.js"></script>
<canvas id="mychart" height="300" width="800"></canvas>
score:22
the code that you were trying to use is actually for chart.js v1 and, as you discovered, does not work for chart.js v2 (which is almost a full chart.js re-write).
to achieve the same results in chart.js v2, you need to extend chart.elements.rectangle
and overwrite it's draw
method in order to paint the rounded top. there is already a chart.js helper method that will draw a rounded rectangle (chart.helpers.drawroundedrectangle
), so we will modify it slightly and create a new helper method that will only draw a rounded top (instead of all sides).
// draws a rectangle with a rounded top
chart.helpers.drawroundedtoprectangle = function(ctx, x, y, width, height, radius) {
ctx.beginpath();
ctx.moveto(x + radius, y);
// top right corner
ctx.lineto(x + width - radius, y);
ctx.quadraticcurveto(x + width, y, x + width, y + radius);
// bottom right corner
ctx.lineto(x + width, y + height);
// bottom left corner
ctx.lineto(x, y + height);
// top left
ctx.lineto(x, y + radius);
ctx.quadraticcurveto(x, y, x + radius, y);
ctx.closepath();
};
chart.elements.roundedtoprectangle = chart.elements.rectangle.extend({
draw: function() {
var ctx = this._chart.ctx;
var vm = this._view;
var left, right, top, bottom, signx, signy, borderskipped;
var borderwidth = vm.borderwidth;
if (!vm.horizontal) {
// bar
left = vm.x - vm.width / 2;
right = vm.x + vm.width / 2;
top = vm.y;
bottom = vm.base;
signx = 1;
signy = bottom > top? 1: -1;
borderskipped = vm.borderskipped || 'bottom';
} else {
// horizontal bar
left = vm.base;
right = vm.x;
top = vm.y - vm.height / 2;
bottom = vm.y + vm.height / 2;
signx = right > left? 1: -1;
signy = 1;
borderskipped = vm.borderskipped || 'left';
}
// canvas doesn't allow us to stroke inside the width so we can
// adjust the sizes to fit if we're setting a stroke on the line
if (borderwidth) {
// borderwidth shold be less than bar width and bar height.
var barsize = math.min(math.abs(left - right), math.abs(top - bottom));
borderwidth = borderwidth > barsize? barsize: borderwidth;
var halfstroke = borderwidth / 2;
// adjust borderwidth when bar top position is near vm.base(zero).
var borderleft = left + (borderskipped !== 'left'? halfstroke * signx: 0);
var borderright = right + (borderskipped !== 'right'? -halfstroke * signx: 0);
var bordertop = top + (borderskipped !== 'top'? halfstroke * signy: 0);
var borderbottom = bottom + (borderskipped !== 'bottom'? -halfstroke * signy: 0);
// not become a vertical line?
if (borderleft !== borderright) {
top = bordertop;
bottom = borderbottom;
}
// not become a horizontal line?
if (bordertop !== borderbottom) {
left = borderleft;
right = borderright;
}
}
// calculate the bar width and roundess
var barwidth = math.abs(left - right);
var roundness = this._chart.config.options.barroundness || 0.5;
var radius = barwidth * roundness * 0.5;
// keep track of the original top of the bar
var prevtop = top;
// move the top down so there is room to draw the rounded top
top = prevtop + radius;
var barradius = top - prevtop;
ctx.beginpath();
ctx.fillstyle = vm.backgroundcolor;
ctx.strokestyle = vm.bordercolor;
ctx.linewidth = borderwidth;
// draw the rounded top rectangle
chart.helpers.drawroundedtoprectangle(ctx, left, (top - barradius + 1), barwidth, bottom - prevtop, barradius);
ctx.fill();
if (borderwidth) {
ctx.stroke();
}
// restore the original top value so tooltips and scales still work
top = prevtop;
},
});
next, you will also have to extend the bar chart controller (chart.controllers.bar
) and overwrite dataelementtype
to use the new "rounded rectangle" for the chart instead of a regular rectangle.
chart.defaults.roundedbar = chart.helpers.clone(chart.defaults.bar);
chart.controllers.roundedbar = chart.controllers.bar.extend({
dataelementtype: chart.elements.roundedtoprectangle
});
lastly, we will modify the chart's config to use the new chart type created above and add a new options property called barroundness
to control how round the top is (0 is flat, 1 is a semi-circle).
var ctx = document.getelementbyid("canvas").getcontext("2d");
var mybar = new chart(ctx, {
type: 'roundedbar',
data: {
labels: ["car", "bike", "walking"],
datasets: [{
label: 'students',
backgroundcolor: chartcolors.blue,
data: [
randomscalingfactor(),
randomscalingfactor(),
randomscalingfactor(),
]
}, {
label: 'teachers',
backgroundcolor: chartcolors.red,
data: [
randomscalingfactor(),
randomscalingfactor(),
randomscalingfactor(),
]
}, {
label: 'visitors',
backgroundcolor: chartcolors.green,
data: [
randomscalingfactor(),
randomscalingfactor(),
randomscalingfactor(),
]
}]
},
options: {
responsive: true,
barroundness: 1,
title: {
display: true,
text: "chart.js - bar chart with rounded tops (drawroundedtoprectangle method)"
},
}
});
you can see a full working example at this codepen.
also, in case you want a slightly different "rounded top" look, here is another codepen that uses a different approach to drawing the top (a single quadratic curve).
Source: stackoverflow.com
Related Query
- How to create rounded bars for Bar Chart.js v2?
- How do you create rounded corners on the top and bottom of a bar chart and the between 2 part still draw like image?
- how to create bar chart with group and sam color for each group using chart.js?
- Chart.js Bar Chart - how to chart bars from 0
- How to put rounded corners on a Chart.js Bar chart
- How to add second Y-axis for Bar and Line chart in Chart.js?
- How to create stacked bar chart using react-chartjs-2?
- How to hide the y axis and x axis line and label in my bar chart for chart.js
- How to have solid colored bars in angular-chart bar chart
- PrimeNg bar chart how to show a label for the y-axis
- How to make bar chart animation where all bars grow at the same speed?
- How to remove bars for those bars with zero value in Chartjs bar chart?
- How to create a chart that uses strings for both the X and Y axes?
- how to customize tool tip while mouse go over bars on Chart js bar chart
- How to show different product name for every bar in chart js
- How to create a variable for chart js datalabel plugin formatter
- How to retain spacing between bars for two different bar charts in Chart.js 2
- How to create Bar chart that gets updated from new ajax requests with ChartJS?
- Chart.js: How to get x-axis labels to show on top of bars in bar chart
- How to use set the color for each bar in a bar chart using chartjs?
- How to draw baseline for bar chart in chart.js
- How do I create a legend for a bar chart?
- How do I create a stacked horizontal bar chart with Chart.js in React?
- How to set X coordinate for each bar with react chart js 2?
- Issue with chartjs linear gradient for the mixed bar chart in ReactJS is not calculated for each individual Bars
- How do I get a different label for each bar in a bar chart in ChartJS?
- How to create dynamically chart for Ionic App with Firebase data?
- How can I create a stacked bar chart with Charts.JS that displays relative rather than absolute values?
- How to prevent empty bars from taking up width in Chart.js bar chart
- ChartJs - stacked bar chart with groups - how to create second x-axis with stack id
More Query from same tag
- chart.js time scatter with true scale
- Trouble using utcoffset with Chart.js
- Rendering Rails json data in chartjs
- Using Createjs and Chartjs
- Loop through array of objects in Node
- React + ChartJS V3: Annoations don't work
- ChartJs Uncaught ReferenceError for labels value from ViewBag
- How to change color by clicking on the chart bar?
- Setting specific color per label in chart.js
- Stacked bars in Charts.js from a JSON list of objects
- Cannot use ng2-charts with Ionic 3 (ionic-angular 3.9.4)
- How to get rid of the line on top of every point on a line chart (Chart.js)
- How to add a custom event on legend click
- How to hide a portion of chart or a div in Angular?
- Chart.js responsive css size
- How can i hide label data on chart.js tooltip content?
- Display Chart(.js) when mouse hover over: TypeError: t is null
- Chart js: bar width
- How to to change mouse cursor on chart.js doughnut graph?
- How can I assign dynamic data from service via subscribe to doughnut chart in angular?
- Chart.js Pie Chart
- Uncaught TypeError: Cannot read property 'draw' of undefined : Angular chart js
- Connecting points between missing data in chart.js
- Multiple Charts of the Same Type in ChartJS2 ReactJS - Buggy Tooltips
- trying to get minIndex and maxIndex from x-axis-0
- How do I change axis, title, legend formatting on chartjs template
- Adjust font-weight in Chart.js doughnut chart
- React-chartjs-2 update height dynamically
- Chart.js: how to listen to hover/click events outside of plot area?
- Chart.js glitches and reverts to previous dataset on hover