Sunday, March 11, 2018

d3 v4 padding inner set to .001 doesn't actually result in small padding between ranges

Leave a Comment

Is there a way to minimize the padding between ranges in a grouped horizontal bar chart?

I am building a horizontal bar chart directive for AngularJS and at the moment I am pretty close but it's the spacing that I am not exactly happy with. If there is a better way to build the vertical ranges I would very much appreciate any tips. Here's my result so far:

angular.module('MissionControlApp').directive('d3GroupedHorizontalBarChart2', ['d3', '$timeout', function(d3, $timeout) {     return {         restrict: 'E',         scope: {             data: '=',             onClick: '&d3OnClick'         },         link: function(scope, ele) {             var refreshScope = function() {                 scope.$apply();             };              var svg = d3.select(ele[0])                 .append("svg")                 .attr("width", "100%");              // on window resize, re-render d3 canvas             window.onresize = function() {                 return scope.$apply();             };             scope.$watch(function(){                     return angular.element(window)[0].innerWidth;                 }, function(){                     return scope.render(scope.data);                 }             );              // watch for data changes and re-render             scope.$watch("data", function(newVals) {                 if(!newVals) return;                 return scope.render(newVals);             }, true);              // define render function for grouped bar charts             scope.render = function(data){                 if(!data) return;                  // remove all previous items before render                 svg.selectAll("*").remove();                  // setup variables                 var margin = {top: 25, right: 40, bottom: 70, left: 150};                 var width = d3.select(ele[0])._groups[0][0].offsetWidth - margin.left - margin.right;                 var height = (scope.data.length * 60);                  svg.attr('height', height + margin.top + margin.bottom);                  var y0 = d3.scaleBand()                     .rangeRound([0, height])                     .paddingInner(0.01);                  var y1 = d3.scaleBand()                     .padding(0.01);                  var x = d3.scaleLinear()                     .rangeRound([0, width]);                  var color = d3.scaleLinear()                     .domain([0, 25, 50, 75, 100])                     .range(["#51b75d", "#90eb9d","#ffff8c","#f5c93f","#c45c44"])                     .interpolate(d3.interpolateHcl);                  var xAxis = d3.axisBottom(x)                     .tickSizeInner(-(height-5))                     .tickPadding(8);                  var keys = d3.keys(data[0]).filter(function(key) { return key !== "user"; });                 y0.domain(data.map(function(d) { return d.user; }));                 y1.domain(keys).rangeRound([0, y0.bandwidth()]);                 x.domain([0, 100]);                  // Define bars                 var bar = svg.selectAll(".bar")                     .data(data)                     .enter().append("g")                     .attr("transform", function(d) { return "translate(" + margin.left + "," + (y0(d.user) + (y0.bandwidth()/2) + margin.top - y1.bandwidth()) + ")"; });                  var barEnter = bar.selectAll("rect")                     .data(function(d) { return d.values; })                     .enter();                  barEnter.append("rect")                     .attr("height", y1.bandwidth())                     .attr("y", function(d) {return y1(d.name); })                     .attr("x", 0)                     .attr("value", function(d){return d.name;})                     .attr("width", 0)                     .attr("fill", function(d) { return color(d.value); })                     .on("mouseover", function() { d3.select(this).style("cursor", "pointer");})                     .on("mouseout", function() { d3.select(this).style("cursor", "default");})                     .on("click", function(d){                         scope.onClick({item: d});                         d3.select(".selectedBlueFill").classed("selectedBlueFill", false);                         d3.select(this).classed("selectedBlueFill", true);                         $timeout(refreshScope, 0, false); // flush the digest cycle                     })                     .transition()                     .duration(1000)                     .attr("width", function(d) { return x(d.value); });                  barEnter.append("text")                     .attr("fill", "#000")                     .attr("y", function(d){return y1(d.name) + (y1.bandwidth() / 2);})                     .attr("x", function(d){return x(d.value);})                     .attr("dx", 5)                     .attr("dy", ".35em")                     .text(function(d){return parseFloat(d.value).toFixed(0) + "%";})                     .attr("fill-opacity", 0)                     .transition()                     .duration(1500)                     .attr("fill-opacity", 1);                  // Set up x axis                 svg.append("g")                     .attr("class", "axisHorizontal")                     .attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")                     .call(xAxis);                  // Set up y axis                 svg.append("g")                     .attr("class", "y axis")                     .attr("transform", "translate(" + margin.left + "," + margin.top + ")")                     .call(d3.axisLeft(y0));                  // Draw the legend                 // Create the gradient for the legend                 svg.append("defs")                     .append("linearGradient")                     .attr("id", "legend-traffic")                     .attr("x1", "0%").attr("y1", "0%")                     .attr("x2", "100%").attr("y2", "0%")                     .selectAll("stop")                     .data(color.range())                     .enter().append("stop")                     .attr("offset", function(d,i) { return i/(color.range().length-1); })                     .attr("stop-color", function(d) { return d; });                  // Legend variables                 var legendWidth = width * 0.6;                 var legendHeight = 10;                  // Legend container                 var legendSvg = svg.append('g')                     .attr("class", "legendWrapper")                     .attr("transform", "translate(" + ((width + margin.left + margin.right)/2) + "," + (height + margin.top + margin.bottom) + ")");                  // Draw the rectangle                 legendSvg.append("rect")                     .attr("class", "legendRect")                     .attr("x", -legendWidth/2)                     .attr("y", -30)                     .attr("width", legendWidth)                     .attr("height", legendHeight)                     .attr("fill", "url(#legend-traffic)");                  // Append title                 legendSvg.append("text")                     .attr("class", "legendTitle")                     .attr("x", 0)                     .attr("y", -35)                     .attr("text-anchor", "middle")                     .text("Worksets Opened %");                  // Set scale for x-axis                 var xScale = d3.scaleLinear()                     .range([0, legendWidth])                     .domain([0,100]);                  // Define x-axis                 var legendAxis = d3.axisBottom(xScale).ticks(5);                  // Set up x-axis                 legendSvg.append("g")                     .attr("class", "axisLegend")                     .attr("transform", "translate(" + (-legendWidth/2) + "," + (legendHeight-30) + ")")                     .call(legendAxis);             };         }     }; }]); 

However the result I am getting is with large inner spacing. I am setting the .paddingInner property to 0.001 and still pretty much end up with large spacing......ideas?

enter image description here

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment