score:1

Accepted answer

Not a clean implementation, since I did not implement select, enter, append pattern of D3, also I add a random color generator, I will leave it to you to clean it up and add your color scheme to the chart

You might notice that the last element missing its color and polygon item since there is no indication on how to add it.

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
    y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var data = [
  {"ind": "Examined", tot_cases: 25000},
  {"ind": "Notified", tot_cases: 17000},
  {"ind": "Initiated", tot_cases: 10000},
  {"ind": "HIV Stat. Confirmed", tot_cases: 14000},
  {"ind": "HIV Unknown", tot_cases:15000}
]

var stroke_colors = {
  "Examined": '#2B597C',
  "Notified": "#6D5C7E",
  "Initiated": '#BF6D84',
  "HIV Stat. Confirmed": '#F1737E',
  "HIV Unknown": '#F9B294'
}

var color = ["#2B597C","#6D5C7E","#BF6D84","#F1737E","#F9B294"]

  var line = d3.line()
    .x(function(d) { return x(d.ind); })
    .y(function(d) { return y(d.tot_cases); })

  x.domain(data.map(function(d) { return d.ind; }));

  y.domain([0, d3.max(data, function(d) { return d.tot_cases; })]);

  g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));



  var lineAndDots = g.append("g")
    		.attr("class", "line-and-dots")
        .attr("transform", "translate(" + ((margin.left + margin.right) / 3) + "," + 0 + ")")

    // Data line
    lineAndDots.append("path")
        .datum(data)
        .attr("class", "data-line")
        .attr("d", line)
        .style('stroke', function(d){ 
              for(i = 0; i < 5; i++){
             return stroke_colors[d[i].ind];}})
        .style('fill', 'none')

    // Data dots
    lineAndDots.selectAll("line-circle")
    		.data(data)
    	.enter().append("circle")
        .attr("class", "data-circle")
        .attr("r", 5)
        .attr("cx", function(d) { return x(d.ind); })
        .attr("cy", function(d) { return y(d.tot_cases); })

  g.selectAll("lines-ax")
    		.data(data)
    	.enter().append("line")
        .attr("class", "line")
        .attr("x1", function(d) { return x(d.ind) + margin.right; })
        .attr("y1", function(d) { return height})
        .attr("x2", function(d) { return x(d.ind) + margin.right ; })
        .attr("fill", "black")
        .attr("stroke", "#F2F2F2")
        .attr("stroke-width", 3);

  

  for(let i=1; i< data.length; i++) {
    let points = [];
    points[0] = {x: x(data[i-1].ind) + margin.right, y: y(data[i-1].tot_cases)};
    points[1] = {x: x(data[i].ind) + + margin.right, y: y(data[i].tot_cases)};
    points[2] = {x: x(data[i].ind) + + margin.right, y: height};
    points[3] = {x: x(data[i-1].ind) + margin.right, y: height};
    points[4] = {x: x(data[i-1].ind) + margin.right, y: y(data[i-1].tot_cases)};
    g.append("polygon")
    .attr("points",  points.map(function(d) { return [d.x,d.y].join(","); }).join(" "))
    .attr("stroke","red")
    .attr("stroke-width", 2)
    .attr('fill', getRandomRgb());
  }

  let points = [];
  points[0] = {x: x(data[data.length - 1].ind) + margin.right, y: y(data[data.length - 1].tot_cases)};

  points[1] = {x: x(data[data.length - 1].ind) + margin.right + 150, y: y(data[data.length - 1].tot_cases)};
  points[2] = {x: x(data[data.length - 1].ind) + margin.right + 150, y: height};

  points[3] = {x: x(data[data.length - 1].ind) + margin.right, y: height};
  points[4] = {x: x(data[data.length - 1].ind) + margin.right, y: y(data[data.length - 1].tot_cases)};

  g.append("polygon")
    .attr("points",  points.map(function(d) { return [d.x,d.y].join(","); }).join(" "))
    .attr("stroke","red")
    .attr("stroke-width", 2)
    .attr('fill', getRandomRgb());

  function getRandomRgb() {
    const num = Math.round(0xffffff * Math.random());
    const r = num >> 16;
    const g = num >> 8 & 255;
    const b = num & 255;
    return 'rgb(' + r + ', ' + g + ', ' + b + ')';
  }
body {  
  font-family: 'Droid Sans', sans-serif;  
}
  
.axis {
	font-size: 14px;
  font-weight: bold;
}
  
text {
  fill: #727075;
  stroke: none;
}

.axis path,
.axis line {
  fill: none;
  stroke: none;
  stroke-width: 2px;
  shape-rendering: crispEdges;
}

.grid path {
  stroke: none;
}

.grid line {
  stroke: #E0E0E0;
  shape-rendering: crispEdges;
}
  
.data-line {
  fill: none; 
stroke: url(#line-gradient);
  stroke-width: 1px;
}
  
.data-circle {
	fill: #3C92BA;     
}
  
.axis-title {
	text-anchor: end;
  fill: #5D6971;
  font-weight: normal;
}
  
.axis-tspan {
	font-size: 12px;
}
<!DOCTYPE html>
<html>
  <head>
    <style>
      

      </style>
  </head>
<body>
  <svg width="960" height="500"></svg>

  <script src="https://d3js.org/d3.v5.min.js"></script>

</body>
</html>


Related Query

More Query from same tag