Created
June 28, 2019 09:48
-
-
Save nwkm/ed32a34ea66d156b3af9dbaa92070a53 to your computer and use it in GitHub Desktop.
Chart helper to get rounded bar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //draws a rectangle with a rounded top | |
| Chart.helpers.drawRoundedTopRectangle = function( | |
| ctx: any, | |
| x: number, | |
| y: number, | |
| width: number, | |
| height: number, | |
| radius: number, | |
| ) { | |
| 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 as any).elements.RoundedTopRectangle = (Chart as any).elements.Rectangle.extend( | |
| { | |
| draw() { | |
| const ctx = this._chart.ctx; | |
| const vm = this._view; | |
| let left; | |
| let right; | |
| let top; | |
| let bottom; | |
| let signX; | |
| let signY; | |
| let borderSkipped; | |
| let borderWidth = vm.borderWidth; | |
| if (!vm.horizontal) { | |
| // bar | |
| left = vm.x - vm.width / 2; | |
| right = vm.x + vm.width / 2; | |
| top = vm.y; | |
| // If the y-axis stack is true, we should increase bottom value by xxx | |
| // vm.base + xxx ===> Help to lower the stacked bar to make they look nice | |
| 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. | |
| const barSize = Math.min( | |
| Math.abs(left - right), | |
| Math.abs(top - bottom), | |
| ); | |
| borderWidth = borderWidth > barSize ? barSize : borderWidth; | |
| const halfStroke = borderWidth / 2; | |
| // Adjust borderWidth when bar top position is near vm.base(zero). | |
| const borderLeft = | |
| left + (borderSkipped !== 'left' ? halfStroke * signX : 0); | |
| const borderRight = | |
| right + | |
| (borderSkipped !== 'right' ? -halfStroke * signX : 0); | |
| const borderTop = | |
| top + (borderSkipped !== 'top' ? halfStroke * signY : 0); | |
| const 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 | |
| const barWidth = Math.abs(left - right); | |
| const roundness = this._chart.config.options.barRoundness || 0.5; | |
| const radius = barWidth * roundness * 0.5; | |
| // keep track of the original top of the bar | |
| const prevTop = top; | |
| // move the top down so there is room to draw the rounded top | |
| top = prevTop + radius; | |
| const 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; | |
| }, | |
| }, | |
| ); | |
| Chart.defaults.roundedBar = Chart.helpers.clone(Chart.defaults.bar); | |
| Chart.controllers.roundedBar = Chart.controllers.bar.extend({ | |
| dataElementType: (Chart as any).elements.RoundedTopRectangle, | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment