score:2

Accepted answer

Since you need to know both current entry weight (for the width), as well as the sum of all previous entries' weights (for the offset), a pie layout seems like an unexpectedly decent fit for the task (since it provides start and end angles for the slices). All you need to do is to map the angle to the width.

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
</head>

<body>
  <script>
    // Feel free to change or delete any of the code you see in this editor!
    var svg = d3.select("body").append("svg")
      .attr("width", 500)
      .attr("height", 200)

    var data = [{
      freq: 60,
      weight: 10
    }, {
      freq: 25,
      weight: 10
    }, {
      freq: 55,
      weight: 20
    }];
    
    var xScale = d3.scaleLinear()
    	.domain([0, Math.PI * 2])
    	.range([0, 500]);
    
    var yScale = d3.scaleLinear()
    	.domain([0, 80])
    	.range([200, 0]);
    
    var pie = d3.pie()
    	.sortValues(null)
    	.value(function(d){ return d.weight; });
    var adjustedData = pie(data);
    
    var rects = svg.selectAll('rect')
    	.data(adjustedData);
    
    rects.enter()
    	.append('rect')
    	.style('fill', 'blue')
    	.style('stroke', 'black')
    .merge(rects)
    	.attr('x', function(d) { return xScale(d.startAngle); })
    	.attr('width', function(d) { return xScale(d.endAngle) - xScale(d.startAngle); })
    	.attr('y', function(d) { return yScale(d.data.freq); })
    	.attr('height', function(d) { return yScale(0) - yScale(d.data.freq); });
    
  </script>
</body>


Related Query

More Query from same tag