Quantcast
Channel: User i alarmed alien - Stack Overflow
Viewing all articles
Browse latest Browse all 42

Answer by i alarmed alien for D3 Horizontal grouped stacked chart bars overlap for a small number of values

$
0
0

Your problem is with the offset of the bars from each other; if you hard-code a value, e.g. using translate(0,29), you are going to be in trouble when the chart data changes, and that makes the bars change size, too. To prevent that happening, set the translate value relative to the size of the bar:

//Appends first bar   var bars = categoryGroup.append("rect")  .attr("width", function(d) { return xScale(d.num); })  .attr("height", y0.rangeBand()/2.5 )  .attr("class", "g-num")var bars2 = categoryGroup.append("rect")  .attr("width", function(d) { return xScale(d.num2); })  .attr("height", y0.rangeBand()/2.5 )  .attr("class", "g-num2")  .attr("transform", "translate(0,"+ ( y0.rangeBand()/2.5 ) +")");

This way, no matter how many or how few bars you have in the chart, the offset of bars2 will always be the same size as the height of the bars, i.e. y0.rangeBand()/2.5.

I'd advise you to standardise the bar label position in a similar manner, but add in a fixed y offset using the dy attribute:

//Appends first bar labels   var barLabels = labelGroup.append("text")   .text(function(d) {return  d.num;})  .attr("x", function(d) { return xScale(d.num) - 20; })  .attr("y", y0.rangeBand()/2.5 ) // note: use 2.5, rather than 2.65  .attr('dy', '-0.35em')          // fixed y offset, set relative to the text size  .attr("class", "g-labels");    //Appends second bar labels   var barLabels2 = labelGroup.append("text")   .text(function(d) {return  d.num2;})  .attr("x", function(d) { return xScale(d.num2) - 20; })  .attr("y", y0.rangeBand()/1.25 )  .attr('dy', '-0.35em')          // fixed y offset  .attr("class", "g-labels");      

Here's your full example:

/* ----- Data ----- */var json_data = {"headers":["Month","Country","Number"],"rows":[["2018-05-01 00:00:00.0","Germany",19],["2018-05-01 00:00:00.0","United Kingdom",23],["2018-04-01 00:00:00.0","Germany",21],["2018-04-01 00:00:00.0","United Kingdom",129] ]};var dataRows = json_data.rows;/* ----- !Data ----- *//* ----- Functions ----- *///Create dictionary function (transformed JSON)createDict = (data) => {  let groups = data.reduce((acc, arr) => {    if (acc.hasOwnProperty(arr[1])) {      acc[arr[1]].push(arr);    } else {      acc[arr[1]] = [arr];    }    return acc;  }, {});  let results = [];  for (let g in groups) {    let obj = {Value: g};    let a = groups[g][0];    let b = groups[g][1];    if (a[0] <= b[0]) {      obj.num = a[2];      obj.num2 = b[2];    } else {      obj.num = b[2];      obj.num2 = a[2];    }    results.push(obj);  }  return results;}//Returns unique values of a specific object of a JSON stringuniqueValues = (data,objectNum) => {var uniqueValues = [];data.forEach(function(item) {    var value = item[objectNum];    if (uniqueValues.indexOf(value) !== -1)    return false;    uniqueValues.push(value);});return uniqueValues;}//Chart creation functioncreateChart = (data) => {  //Margin conventions  console.log(data)  var margin = {top: 10, right: 50, bottom: 20, left: 70};  var widther = window.outerWidth;  var width = widther - margin.left - margin.right,      height = 400 - margin.top - margin.bottom;  //Appends the svg to the chart-container div  var svg = d3.select(".g-chart").append("svg")    .attr("width", width + margin.left + margin.right)    .attr("height", height + margin.top + margin.bottom)    .append("g")    .attr("transform", "translate("+ margin.left +","+ margin.top +")");  //Creates the xScale   var xScale = d3.scale.linear()    .range([0,width]);  //Creates the yScale  var y0 = d3.scale.ordinal()    .rangeBands([height, 0], 0.2)     .domain(uniqueValues);    console.log(d3.scale.ordinal().rangeBands([height, 0], 0.2) );    //.domain(["Spain", "UK", "Germany", "France", "Italy"]);  //Defines the y axis styles  var yAxis = d3.svg.axis()    .scale(y0)    .orient("left");  //Defines the y axis styles  var xAxis = d3.svg.axis()    .scale(xScale)    .orient("bottom")    .tickFormat(function(d) {return d; })    //Change axis values for percentage    //.tickFormat(function(d) {return d +"%"; })    .tickSize(height)    .ticks(numTicks(width));     //FORMAT data    data.forEach(function(d) {      d.num = +d.num;    });    //Sets the max for the xScale    var maxX = d3.max(data, function(d) { return d.num; });    //Defines the xScale max    xScale.domain([0, maxX ]);    //Appends the y axis    var yAxisGroup = svg.append("g")      .attr("class", "y axis")      .call(yAxis);    //Appends the x axis        var xAxisGroup = svg.append("g")      .attr("class", "x axis")      .call(xAxis);     //Binds the data to the bars          var categoryGroup = svg.selectAll(".g-category-group")      .data(data)      .enter()      .append("g")      .attr("class", "g-category-group")      .attr("transform", function(d) {        return "translate(0,"+ y0(d.Value) +")";      });    //Appends first bar       var bars = categoryGroup.append("rect")      .attr("width", function(d) { return xScale(d.num); })      .attr("height", y0.rangeBand()/2.5 )      .attr("class", "g-num")//      .attr("transform", "translate(0,4)");    //Appends second bar       var bars2 = categoryGroup.append("rect")      .attr("width", function(d) { return xScale(d.num2); })      .attr("height", y0.rangeBand()/2.5 )      .attr("class", "g-num2")      .attr("transform", "translate(0,"+ ( y0.rangeBand()/2.5 ) +")");      //Binds data to labels    var labelGroup = svg.selectAll("g-num")      .data(data)      .enter()      .append("g")      .attr("class", "g-label-group")      .attr("transform", function(d) {        return "translate(0,"+ y0(d.Value) +")";      });    //Appends first bar labels       var barLabels = labelGroup.append("text")       .text(function(d) {return  d.num;})      .attr("x", function(d) { return xScale(d.num) - 20; })      .attr("y", y0.rangeBand()/2.5 )      .attr('dy', '-0.35em')      .attr("class", "g-labels");        //Appends second bar labels       var barLabels2 = labelGroup.append("text")       .text(function(d) {return  d.num2;})      .attr("x", function(d) { return xScale(d.num2) - 20; })      .attr("y", y0.rangeBand()/1.25 )      .attr('dy', '-0.35em')      .attr("class", "g-labels");          //Appends chart source    d3.select(".g-source-bold")      .text("SOURCE: ")      .attr("class", "g-source-bold");    d3.select(".g-source-reg")      .text("Chart source info goes here")      .attr("class", "g-source-reg");      //RESPONSIVENESS    d3.select(window).on("resize", resized);    function resized() {      //new margin      var newMargin = {top: 10, right: 80, bottom: 20, left: 50};      //Get the width of the window      var w = d3.select(".g-chart").node().clientWidth;      console.log("resized", w);      //Change the width of the svg      d3.select("svg")        .attr("width", w);      //Change the xScale      xScale        .range([0, w - newMargin.right]);      //Update the bars      bars        .attr("width", function(d) { return xScale(d.num); });      //Update the second bars      bars2        .attr("width", function(d) { return xScale(d.num2); });        //Updates bar labels      barLabels        .attr("x", function(d) { return xScale(d.num) - 20; })        .attr("y", y0.rangeBand()/2.65 )      //Updates second bar labels      barLabels2        .attr("x", function(d) { return xScale(d.num2) - 20; })        .attr("y", y0.rangeBand()/1.25 )        //Updates xAxis      xAxisGroup        .call(xAxis);         //Updates ticks      xAxis        .scale(xScale)        .ticks(numTicks(w));    };  //}  //Determines number of ticks base on width  function numTicks(widther) {    if (widther <= 400) {      return 4      console.log("return 4")    }    else {      return 10      console.log("return 5")    }  }}/* ----- !Functions ----- */ /* ----- Main ----- */var data = createDict(dataRows);//Calculate unique Values var uniqueValues = uniqueValues(dataRows,1);createChart(data);/* ----- !Main ----- */
/*css to go here*/  @import url(https://fonts.googleapis.com/css?family=Karla);  body {    font-family: 'Karla', sans-serif;    font-size: 12px;  }  .g-hed {    text-align: left;    text-transform: uppercase;    font-weight: bold;    font-size:22px;     margin: 3px 0;  }  .g-source-bold {    text-align: left;    font-size:10px;    font-weight: bold;   }  .g-source {    margin: 10px 0;  }  .g-source-bold {    text-align: left;    font-size:10px;   }  .g-intro {    font-size: 16px;    margin: 0px 0px 10px 0px;  }  .g-num {    fill:#124;  }   .g-num2 {     fill:#ccc;  }  .g-labels {    fill: white;    font-weight: bold;    font-size: 13px;  }  .axis line {    fill: none;    stroke: #ccc;    stroke-dasharray: 2px 3px;    shape-rendering: crispEdges;    stroke-width: 1px;  }  .axis text {    font-size: 13px;    pointer-events: none;    fill: #7e7e7e;  }  .domain {    display: none;  }  .y.axis text {    text-anchor: end !important;    font-size:14px;    fill: #000000;  }  .y.axis line {    display: none;  }  .g-baseline line {    stroke:#000;    stroke-width: 1px;    stroke-dasharray:none;  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script><body><h5 class="g-hed"></h5><p class="g-intro"></p><div class="g-chart"></div><div class="g-source"><span class="g-source-bold"></span><span class="g-source-reg"></span></div></div></body>

Viewing all articles
Browse latest Browse all 42

Trending Articles