percent bar

by abenrob

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<div ng-app="MyApp">
    <div class="pctbox" ng-controller="MyController">
         <pctbar chart-data="data" chart-height="30" colors="colors"></pctbar>
    </div>
</div>

CSS

.pctbox {
    width: 300px;
}
.outline {
    fill: none;
    stroke: #666;
    stroke-width: .25px;
}
.bartext, .pcttext {
    font-size: 12px;
    font-family: 'Arial';
}
.pcttext {
    fill: #FFF;
}
.bartext {
    fill: #666;
    font-style: uppercase;
}

JavaScript

var myApp = angular.module('MyApp', []);
myApp.directive('pctbar', function () {
        var link = function (scope, elem, attrs) {
            // Scale the range of the data
            function setData(){
                var elemHeight = scope.chartHeight || 30;
                var elemWidth = scope.chartWidth || 300;
                var margin = {top: 5, right: 5, bottom: 5, left: 5};
                var pctbar = d3.select(elem[0])
                            .append("svg")
                                .style('height', elemHeight+20+'px')
                                .style('width', '100%')
                            .append('g')
                                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
                
                // Set the dimensions of the canvas / graph
                var width = elemWidth - margin.left - margin.right,
                    height = elemHeight - margin.top - margin.bottom;
                
                // Set the ranges
                var x = d3.scale.linear()
                    .rangeRound([0, width]);
                
                var colors = scope.colors || d3.scale.category10().range(); 
                
                var data = scope.chartData;
            
                var total = d3.sum(data, function(d) {return d.value; });
                var x0 = 0;
                
                data.forEach(function(d,i) { 
                    d.x0 = x0; 
                    d.pct = 100*(d.value/total);
                    d.x1 = (d.pct)+x0; 
                    d.width = d.x1 - d.x0;
                    if (i == 0) { 
                        d.textalign = 'start';
                        d.textX = 0;
                    } else if (i == data.length-1) { 
                        d.textalign = 'end';
                        d.textX = 100;
                    } else { 
                        d.textalign = 'middle';
                        d.textX = d.x0 + ((d.x1 - d.x0) /...