How can we construct multiple Circle PackLayout (basis keys) on predefined x, y location in D3.js?

88 views Asked by At

js experts, Need your help. I have been working hard for last 2 days but could not get thru. I have COVID-19 data grouped by cumulative cases as on month end (28th Feb, 31st Mar & so on). Transformed the x,y location for 9 months as under:

var margin = {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  },
  width = 700 - margin.left - margin.right,
  height = 700 - margin.top - margin.bottom

var svg = d3.select("body").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", function(d, i) {
    return "translate(" + [width / 2, height / 2] + ")";
  })

var parseDate = d3.timeParse("%m/%d/%y");
var formatDate = d3.timeFormat("%b-%y");

var angleScale = d3.scaleLinear().range([0, 2 * Math.PI - 0.5])
angleScale.domain([new Date(2020, 2, 1), new Date(2020, 2, 31)])

var radius = width * 0.4

var radiusScale = d3.scaleLinear().range([0, radius]).domain([0, 100000]);

var data = [];
["Afghanistan", "Albania", "Algeria", "Andorra"].forEach(function(c) {
  var cum = 1;
  var date = new Date(angleScale.domain()[0]);
  while (date <= angleScale.domain()[1]) {
    data.push({
      country: c,
      date: new Date(date),
      // Simulate exponential growth
      cum: Math.floor(cum *= (1 + Math.random() * 0.3)),
    });
    date.setDate(date.getDate() + 1);
  }
});

var nestedData = d3.nest()
  .key(function(d) {
    return d.date
  })
  .entries(data)

nestedData.sort(function(a, b) {
  return a.values - b.values
})

packableData = {
  id: "root",
  values: nestedData
}

var packLayout = d3.pack()
  .size([100, 100])

root = d3.hierarchy({
    values: nestedData
  }, function(d) {
    return d.values;
  })
  .sum(function(d) {
    return d.cum;
  })
  .sort(function(a, b) {
    return b.height - a.height || b.value - a.value;
  })

date_location_data = root.leaves()
packLayout(root);

const circle_data = [new Date(2020, 2, 28), new Date(2020, 3, 31), new Date(2020, 4, 30), new Date(2020, 5, 31), new Date(2020, 6, 30), new Date(2020, 7, 31), new Date(2020, 8, 31), new Date(2020, 9, 30), new Date(2020, 10, 16)]

var Maincell = svg.selectAll('.date-group')
  .data(circle_data)
  .enter()
  .append("g")
  .attr("class", 'date-group')
  .attr("transform", function(d, i) {
    var x = radiusScale(90000) * Math.cos(angleScale(d)),
      y = radiusScale(90000) * Math.sin(angleScale(d))
    return "translate(" + [x, y] + ")";
  })

var cell = Maincell
  .selectAll(".node")
  .data(date_location_data)
  .enter().append("g")
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  })
  .attr("class", "node")

cell.append("circle")
  .attr("id", function(d) {
    return "node-" + d.name;
  })
  .attr("r", function(d) {
    return d.r;
  })
  .attr("class", "circle")
  .style("fill", function(d) {
    return "red";
  })
  .style("opacity", 1)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

The specimen csv file is as:

Country,Date,cum
Afghanistan,2/28/20,1
Albania,2/28/20,0
Algeria,2/28/20,1
Andorra,2/28/20,0
....
Yemen,10/16/20,2055
Zambia,10/16/20,15659
Zimbabwe,10/16/20,8099

I am getting the circle pack for entire data repeating at all 9 locations. I need your help in such that circle pack for that particular date (28th Feb, 31st Mar) appear at transformed location defined above.

Many thanks,

0

There are 0 answers