nhulz / nhulz.github.io

Generic repository for hosting class projects
0 stars 0 forks source link

Forming Pack Data in V4 #2

Open nhulz opened 7 years ago

nhulz commented 7 years ago

Unfortunately I've had little to no luck finding any tutorials on data packing with the D3 V4 so this has been challenging.

From what I've gathered, d3.pack() is the new function, and I need to give it a "root node" in order for it to work. So I've been trying to figure out what function I use now to format the data so that d3.pack() can use it. The closest I've got to this is the d3.heirarchy() function, but I'm still uncertain about what exactly it's doing or how to then use that data in the draw function.

var margin = {top: 100, right: 100, bottom: 100, left: 250},
    DotChartWidth = 1500 - margin.left - margin.right,
    DotChartHeight = 1500 - margin.top - margin.bottom;

// add the graph canvas to the body of the webpage
var dotChartSVG = d3.select("#dotChartSVG")
    .attr("width", DotChartWidth + margin.left + margin.right)
    .attr("height", DotChartHeight + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var yScale = d3.scaleOrdinal()
  .domain(["Strongly disagree", "Somewhat disagree", "Neither agree nor disagree", "Somewhat agree", "Strongly agree"])
  .range([100, 200, 300, 400, 500]);

var xScale = d3.scaleOrdinal()
  .domain(["Immediately/ We've always slept in separate beds", "Within the first 1-5 years of our relationship", "Within 6-10 years of our relationship", "Within 11-15 years of our relationship", "Within 16-20 years of our relationship", "After 20 years of our relationship"])
  .range([100, 300, 500, 700, 900, 1100]);

// Setting up pack
var pack = d3.pack()
    .size([DotChartWidth, DotChartHeight])
    .padding(1);
// Trying to get data into nodes, I used hierarchy but isn't my data flat?
// Just need to figure out how to get the nodes and x and y
var nodes = d3.hierarchy(dotChartData);

// This logs an array of data, that array has an x and y, but none of the objects within it do.
    console.log(pack(nodes));

function dotChartfunction(key){

// trying to create each node and then append the circles to the nodes
  var node = dotChartSVG.selectAll(".node")
      .data(pack(nodes))
      .enter()
      .append("g")
        .attr("class", "node")
        .attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });

  var circles = dotChartSVG.selectAll("circle").data(nodes);

  // enter animation for the first time this function is run
  node.append("circle")
    .attr("cy", function(d){
      return yScale(d[key]);
    })
    .attr("cx", function(d){
      return xScale(d.firstSeparateBed);
    })
    .attr("r", 0)
    .transition().duration(1000)
    .attr("r", 5);

  // update the x and y coordinates when running this function after the first time
  circles
    .transition().duration(1000)
    .attr("cy", function(d){
      return yScale(d[key]);
    })
    .attr("cx", function(d){
      return xScale(d.firstSeparateBed);
    });

  // ...technically, as is, this exit animation will never run, because the data does not change (only the key used to position the circles)
  circles.exit()
    .transition().duration(1000).ease("exp")
    .attr("r", 0)
    .remove();

}

// simply pass the key to be used to the function as a string
d3.select('#sexBtn').on('click', function(d, i) {
  dotChartfunction("sexImproved");
})

d3.select('#relationshipBtn').on('click', function(d, i) {
  dotChartfunction("stayingTogether");
});

dotChartfunction("stayingTogether");
davelandry commented 7 years ago

Hmm yeah, his new pack layout is a little tricky. Give this a try (your arch-nemesis d3.nest makes an appearance):


var radius = 3;

function dotChartfunction(key){

  var pack = d3.pack()
    .size([200, 100])
    .radius(function(){ return radius; })
    .padding(1);

  var groupedData = d3.nest()
    .key(function(d) {
      return d[key] + d.firstSeparateBed;
    })
    .entries(dotChartData);

  var packedData = [];
  groupedData.forEach(function(d) {

    // nests the data for the pack layout
    var root = d3.hierarchy(d, function(l) { return l.values; })
      .sum(function(l) { return 1; });

    packedData = packedData.concat(pack(root).children);

  });

  var circles = dotChartSVG.selectAll("circle").data(packedData);

  function circlePosition(circle) {
    circle
      .attr("cy", function(d){
        return yScale(d.data[key]) + d.y - 50;
      })
      .attr("cx", function(d){
        return xScale(d.data.firstSeparateBed) + d.x - 100;
      });
  }

  // enter animation for the first time this function is run
  circles.enter().append("circle")
    .call(circlePosition)
    .attr("r", 0)
    .transition().duration(1000)
    .attr("r", radius);

  // update the x and y coordinates when running this function after the first time
  circles
    .transition().duration(1000)
    .call(circlePosition);

}
davelandry commented 7 years ago

I'll be online tomorrow morning if you have any more questions before Tuesday (but I tested this on my computer and man does it look sexy).

nhulz commented 7 years ago

Holy crap this looks so cool. Thanks Dave!