javascript - How to create rounded bars for Bar Chart.js v2? -
trying round bars on bar chart found in post works displayed in jsfiddle provided. version 1.
in chart using, fails load reference extend
in chart.types.bar.extend
crashes script.
if use default option, chart loads no problems. had place chart.types.bar.extend
@ end default option load correctly. run , view in full screen.
i tried implementing version of chart.js 2.4.0.
chrome reports:
uncaught typeerror: cannot read property 'extend' of undefined chart.js
this code not run here. why occurring? please assist me.
this code works older version of chart.js 1.0. please further display how work version chart.js 2.0? thank you.
$(document).ready(function(){ var mybarchart1 = new chart($('#appbarchart2_noround'), { type: 'bar', data: databar2, options: optionsbar }); var ctx = $("#appbarchart2").getcontext("2d"); var mybarchart2 = new chart(ctx).baralt(databaralt2, { // 0 (flat) 1 (more curvy) curvature: 1 }); }); var databaralt2 = { labels: ["january", "february", "march", "april", "may", "june", "july"], datasets: [ { fillcolor: "#1a9bfc", strokecolor: "#1a9bfc", data: [65, 59, 80, 81, 56, 55, 40], } ] }; var databar2 = { labels: ["january", "february", "march", "april", "may", "june", "july"], datasets: [ { label: "my first dataset", backgroundcolor: '#1a9bfc', bordercolor:'#1a9bfc', borderwidth: 1, data: [65, 59, 80, 81, 56, 55, 40], } ] }; var optionsbar = { scales: { xaxes: [{ stacked: true, barthickness: 20, gridlines:{ display:false, } // barpercentage:0.5, }], yaxes: [{ stacked: true, // barpercentage:0.5, }] }, legend: { display: false, // position: 'left' } }; 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.5; // override rectangle draw ours this.datasets.foreach(function (dataset) { dataset.bars.foreach(function (bar) { bar.draw = function () { // draw original bar little down (so our curve brings original position) var y = bar.y; // min required animation not start below axes bar.y = math.min(bar.y + radius, self.scale.endpoint - 1); // adjust bar radius depending on how of curve can draw var barradius = (bar.y - y); rectangledraw.apply(bar, arguments); // draw 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 y value bar.y = y; } }) }) } } });
<script src="https://cdnjs.cloudflare.com/ajax/libs/chart.js/2.5.0/chart.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div> <p>bar chart - working</p> <canvas id="appbarchart2_noround" height="100" > </div> <div> <p>rounded bar chart - not working</p> <canvas id="appbarchart2" height="100" > </div>
the code trying use chart.js v1 and, discovered, not work chart.js v2 (which full chart.js re-write).
to achieve same results in chart.js v2, need extend chart.elements.rectangle
, overwrite it's draw
method in order paint rounded top. there chart.js helper method draw rounded rectangle (chart.helpers.drawroundedrectangle
), modify , create new helper method draw rounded top (instead of sides).
// draws rectangle 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 stroke inside width can // adjust sizes fit if we're setting stroke on line if (borderwidth) { // borderwidth shold less bar width , 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 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 vertical line? if (borderleft !== borderright) { top = bordertop; bottom = borderbottom; } // not become horizontal line? if (bordertop !== borderbottom) { left = borderleft; right = borderright; } } // calculate bar width , 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 original top of bar var prevtop = top; // move top down there room draw rounded top top = prevtop + radius; var barradius = top - prevtop; ctx.beginpath(); ctx.fillstyle = vm.backgroundcolor; ctx.strokestyle = vm.bordercolor; ctx.linewidth = borderwidth; // draw rounded top rectangle chart.helpers.drawroundedtoprectangle(ctx, left, (top - barradius + 1), barwidth, bottom - prevtop, barradius); ctx.fill(); if (borderwidth) { ctx.stroke(); } // restore original top value tooltips , scales still work top = prevtop; }, });
next, have extend bar chart controller (chart.controllers.bar
) , overwrite dataelementtype
use new "rounded rectangle" chart instead of regular rectangle.
chart.defaults.roundedbar = chart.helpers.clone(chart.defaults.bar); chart.controllers.roundedbar = chart.controllers.bar.extend({ dataelementtype: chart.elements.roundedtoprectangle });
lastly, modify chart's config use new chart type created above , add new options property called barroundness
control how round top (0 flat, 1 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 rounded tops (drawroundedtoprectangle method)" }, } });
you can see full working example @ codepen.
also, in case want different "rounded top" look, here codepen uses different approach drawing top (a single quadratic curve).
Comments
Post a Comment