score:2

Accepted answer

To place rectangles sequentially one method we can use is to specify the properties of each bar if we know them beforehand:

var data = [
  { start: 90, end: 100, color: "lightgreen" },
  { start: 60, end: 90, color: "yellow" },
  { start: 0, end: 60, color: "crimson" }
];

With three items in the data array, we can use an enter selection to place three rectangles in the SVG.

We could programmatically derive the start and end information based on the provided numebrs too, 60,30,10, with some manipulation, but for demonstration I'll just use the above data array:

var svgWidth = 600, svgHeight=400;
  scaleFactor = 20;

var data = [
  { start: 90, end: 100, color: "lightgreen" },
  { start: 60, end: 90, color: "yellow" },
  { start: 0, end: 60, color: "crimson" }
];

var svg = d3.select("body")
 .append("svg")
 .attr("width", svgWidth)
 .attr("height", svgHeight);


var x = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) { return d.end; })])
  .range([0, 300]);


var bar = svg.selectAll("g")
  .data(data)
  .enter()
  .append("g")
  .attr("transform","translate(0," + scaleFactor + ")");
    
bar.append("rect")
 .attr("class", "first")
 .attr("width", function(d) {
   return x(d.end - d.start);  // get the width
 }) 
 .attr("x", function(d) {
   return x(d.start);        // get the start position
 })
 .attr("fill", function(d) { return d.color; })
 .attr("height", 20);
    
    
<script src="https://d3js.org/d3.v5.min.js"></script>

If you really want the rounding we could use a clip path - as a rects rx and ry attributes are applied on all corners:

var svgWidth = 600, svgHeight=400;
  scaleFactor = 20;

var data = [
  { start: 90, end: 100, color: "lightgreen" },
  { start: 60, end: 90, color: "yellow" },
  { start: 0, end: 60, color: "crimson" }
];

var svg = d3.select("body")
 .append("svg")
 .attr("width", svgWidth)
 .attr("height", svgHeight);


var x = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) { return d.end; })])
  .range([0, 300]);


var clip = svg.append("clipPath")
  .attr("id","clip")
  .append("rect")
  .attr("width", 300) // width
  .attr("height", 20)
  .attr("rx", 12)
  .attr("ry", 12);


var bar = svg.selectAll("g")
  .data(data)
  .enter()
  .append("g")
  .attr("transform","translate(0," + scaleFactor + ")");
    
bar.append("rect")
 .attr("class", "first")
 .attr("width", function(d) {
   return x(d.end - d.start);  // get the width
 }) 
 .attr("x", function(d) {
   return x(d.start);        // get the start position
 })
 .attr("fill", function(d) { return d.color; })
 .attr("height", 20)
 .attr("clip-path","url(#clip)");
<script src="https://d3js.org/d3.v5.min.js"></script>

If you really want to use css rather than d3 to style the rectangles you could either specify an identifier to color the bars or use standard css selectors such as nth-of-type:

var svgWidth = 600, svgHeight=400;
  scaleFactor = 20;

var data = [
  { start: 90, end: 100, id: "green"},
  { start: 60, end: 90, id: "yellow"},
  { start: 0, end: 60, id: "red"}
];

var svg = d3.select("body")
 .append("svg")
 .attr("width", svgWidth)
 .attr("height", svgHeight);


var x = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) { return d.end; })])
  .range([0, 300]);


var clip = svg.append("clipPath")
  .attr("id","clip")
  .append("rect")
  .attr("width", 300) // width
  .attr("height", 20)
  .attr("rx", 12)
  .attr("ry", 12);


var bar = svg.selectAll("g")
  .data(data)
  .enter()
  .append("g")
  .attr("transform","translate(0," + scaleFactor + ")");
    
bar.append("rect")
 .attr("class", "first")
 .attr("width", function(d) {
   return x(d.end - d.start);  // get the width
 }) 
 .attr("x", function(d) {
   return x(d.start);        // get the start position
 })
 .attr("id", function(d) { return d.id; })
 .attr("height", 20)
 .attr("clip-path","url(#clip)");
#green {
  fill: lightgreen;
}

#red {
  fill: crimson;
}

#yellow {
  fill: yellow;
}
<script src="https://d3js.org/d3.v5.min.js"></script>


Related Query

More Query from same tag