Canvas Chart bars flat-3d

by PhilQ

HTML

<canvas id="myCanvas" width="550" height="300"></canvas>

CSS

body {
    margin: 0px;
    padding: 2px;
}
canvas {
    float: left;
    width: 550px;
    height: 300px;
    background-color: #c0c0c0;
}

JavaScript

var cnv = document.getElementById('myCanvas');
var ctx = cnv.getContext('2d');
ctx.translate(0.5, 0.5);

var drawChartBars = function(canvas, chartBars) {
    var context = canvas.getContext('2d');
    var paddingLeft = 50;
    var paddingTop = 20;
    var paddingRight = 20;
    var paddingBottom = 50;
    var spacing = 5;
    var topFlatRatio = (1/4);
    var minY = (canvas.height - paddingBottom);
    var maxY = paddingTop;
    var minX = paddingLeft;
    var maxX = (canvas.width - paddingRight);
    
    var cnt = Object.keys(chartBars).length;
    var spacers = (cnt+1);
    var w = (maxX-minX);
    // var tubeWidth = Math.min(50, Math.round((w-(spacers*spacing))/cnt));
    var tubeWidth = Math.round((w-(spacers*spacing))/cnt);
    var tubeTopHeight = Math.floor(tubeWidth*topFlatRatio);
    tubeWidth = (tubeTopHeight/topFlatRatio);
    var halfTubeTopHeight = Math.round(tubeTopHeight/2);
    var halfTubeWidth = Math.round(tubeWidth/2);
    spacing = Math.floor((w-(cnt*tubeWidth))/spacers);
    minX += spacing;
    minY -= halfTubeTopHeight+1;
    maxY += halfTubeTopHeight;
    
    context.lineWidth = 1;
    context.lineJoin = 'round';
    context.lineCap = 'butt';

    for(var k=0; k<cnt; k++) {
        var percentage = chartBars[k].value;
        var color = "rgb("+chartBars[k].color[0]+","+chartBars[k].color[1]+","+chartBars[k].color[2]+")";
        var tubeTop = Math.round(minY-((minY-maxY)*percentage));
        
        /* === chartbar fill === */
        context.beginPath();
        context.moveTo(minX, minY);
        context.lineTo(minX, tubeTop);
        
        context.save();
        context.translate((minX+halfTubeWidth), tubeTop);
        context.scale(1, topFlatRatio);
        context.arc(0, 0, halfTubeWidth, 1 * Math.PI, 0, false);
        context.restore();
    
        context.lineTo((minX+tubeWidth), minY);
    
        context.save();
        context.translate((minX+halfTubeWidth), minY);
        context.scale(1, topFlatRatio);
       ...