0

我正在尝试构建与此类似的 D3 可视化:

流图

来源

我最初开始尝试修改 Bostock 的渐变凹凸示例,但我倾向于认为流图布局在这里可能会更好地为我服务。随着时间的推移,我正在研究食品消费的变化。例如,数据看起来类似于:

group,translation,value,date
"Grain","pearl barley",0,1640,
"Grain","pearl barley",662,1641,
"Grain","pearl barley",0,1642,
"Grain","pearl barley",0,1643,
"Grain","pearl barley",432,1644,
"Grain","pearl barley",789,1645,
"Grain","pearl barley",408.5,1646,
"Grain","pearl barley",0,1647,
"Grain","pearl barley",0,1648,
"Grain","pearl barley",0,1649,
"Grain","pearl barley",0,1650,
"Grain","pearl barley",0,1651,
"Grain","pearl barley",0,1652,
"Grain","pearl barley",0,1653,
"Grain","pearl barley",0,1654,
"Grain","pearl barley",0,1655,
"Grain","pearl barley",0,1656,
"Grain","pearl barley",0,1657,
"Grain","pearl barley",0,1658,
"Grain","pearl barley",0,1659,
"Grain","pearl barley",0,1660,
"Grain","pearl barley",0,1661,
"Grain","pearl barley",0,1662,
"Grain","pearl barley",1808,1663,
"Grain","pearl barley",48,1664,
"Grain","pearl barley",0,1665,
"Grain","pearl barley",0,1666,
"Grain","pearl barley",0,1667,
"Grain","pearl barley",172,1668,
"Grain","pearl barley",0,1669,
"Grain","pearl barley",0,1670,
"Grain","pearl barley",8,1671,
"Grain","pearl barley",0,1672,
"Grain","pearl barley",0,1673,
"Grain","pearl barley",0,1674,
"Grain","pearl barley",0,1675,
"Grain","pearl barley",0,1676,
"Grain","pearl barley",0,1677,
"Grain","pearl barley",0,1678,
"Grain","pearl barley",0,1679,
"Grain","pearl barley",0,1680,
"Grain","pearl barley",48,1681,
"Grain","pearl barley",0,1682,
"Grain","pearl barley",0,1683,
"Grain","pearl barley",0,1684,
"Grain","pearl barley",0,1685,
"Grain","pearl barley",0,1686,
"Grain","pearl barley",0,1687,
"Grain","pearl barley",0,1688,
"Grain","wheat flour",0,1640,
"Grain","wheat flour",0,1641,
"Grain","wheat flour",0,1642,
"Grain","wheat flour",0,1643,
"Grain","wheat flour",0,1644,
"Grain","wheat flour",0,1645,
"Grain","wheat flour",0,1646,
"Grain","wheat flour",0,1647,
"Grain","wheat flour",0,1648,
"Grain","wheat flour",0,1649,
"Grain","wheat flour",0,1650,
"Grain","wheat flour",0,1651,
"Grain","wheat flour",0,1652,
"Grain","wheat flour",0,1653,
"Grain","wheat flour",0,1654,
"Grain","wheat flour",0,1655,
"Grain","wheat flour",0,1656,
"Grain","wheat flour",0,1657,
"Grain","wheat flour",0,1658,
"Grain","wheat flour",0,1659,
"Grain","wheat flour",0,1660,
"Grain","wheat flour",0,1661,
"Grain","wheat flour",0,1662,
"Grain","wheat flour",0,1663,
"Grain","wheat flour",0,1664,
"Grain","wheat flour",0,1665,
"Grain","wheat flour",0,1666,
"Grain","wheat flour",0,1667,
"Grain","wheat flour",0,1668,
"Grain","wheat flour",0,1669,
"Grain","wheat flour",0,1670,
"Grain","wheat flour",0,1671,
"Grain","wheat flour",0,1672,
"Grain","wheat flour",0,1673,
"Grain","wheat flour",0,1674,
"Grain","wheat flour",0,1675,
"Grain","wheat flour",0,1676,
"Grain","wheat flour",0,1677,
"Grain","wheat flour",0,1678,
"Grain","wheat flour",168,1679,
"Grain","wheat flour",0,1680,
"Grain","wheat flour",0,1681,
"Grain","wheat flour",0,1682,
"Grain","wheat flour",0,1683,
"Grain","wheat flour",0,1684,
"Grain","wheat flour",0,1685,
"Grain","wheat flour",0,1686,
"Grain","wheat flour",0,1687,
"Grain","wheat flour",0,1688,

流图布局很简单,可以开始了:

<script>

chart("data/grains.csv", "orange");

var datearray = [];
var colorrange = [];


function chart(csvpath, color) {

  if (color == "blue") {
    colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"];
  }
  else if (color == "pink") {
    colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"];
  }
  else if (color == "orange") {
    colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"];
  }
  strokecolor = colorrange[0];

  var format = d3.time.format("%Y");

  var margin = {top: 20, right: 60, bottom: 30, left: 60};
  var width = document.body.clientWidth - margin.left - margin.right;
  var height = 400 - margin.top - margin.bottom;

  var tooltip = d3.select("body")
      .append("div")
      .attr("class", "remove")
      .style("position", "absolute")
      .style("z-index", "20")
      .style("visibility", "hidden")
      .style("top", "30px")
      .style("left", "55px");

  var x = d3.time.scale()
      .range([0, width]);

  var y = d3.scale.linear()
      .range([height-10, 0]);

  var z = d3.scale.ordinal()
      .range(colorrange);

  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .ticks(d3.time.years);

  var yAxis = d3.svg.axis()
      .scale(y);

  var yAxisr = d3.svg.axis()
      .scale(y);

  var stack = d3.layout.stack()
      .offset("expand")
      .values(function(d) { return d.values; })
      .x(function(d) { return d.date; })
      .y(function(d) { return d.value; });

  var nest = d3.nest()
      .key(function(d) { return d.translation; });

  var area = d3.svg.area()
      .interpolate("cardinal")
      .x(function(d) { return x(d.date); })
      .y0(function(d) { return y(d.y0) - 2; }) // mess with margin
      .y1(function(d) { return y(d.y0 + d.y) + 2; }); // mess with margin

  var svg = d3.select(".chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var graph = d3.csv(csvpath, function(data) {
    data.forEach(function(d) {
      d.date = format.parse(d.date);
      d.value = +d.value;
    });

    var layers = stack(nest.entries(data));

    x.domain(d3.extent(data, function(d) { return d.date; }));
    y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]);

    svg.selectAll(".layer")
        .data(layers)
      .enter().append("path")
        .attr("class", "layer")
        .attr("d", function(d) { return area(d.values); })
        .style("fill", function(d, i) { return z(i); });


    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    // svg.append("g")
    //     .attr("class", "y axis")
    //     .attr("transform", "translate(" + width + ", 0)")
    //     .call(yAxis.orient("right"));

    // svg.append("g")
        // .attr("class", "y axis")
        // .call(yAxis.orient("left"));

    svg.selectAll(".layer")
      .attr("opacity", 1)
      .on("mouseover", function(d, i) {
        svg.selectAll(".layer").transition()
        .duration(250)
        .attr("opacity", function(d, j) {
          return j != i ? 0.6 : 1;
      })})

      .on("mousemove", function(d, i) {
        mousex = d3.mouse(this);
        mousex = mousex[0];
        var invertedx = x.invert(mousex);
        invertedx = invertedx.getFullYear() + invertedx.getDate();
        var selected = (d.values);
        for (var k = 0; k < selected.length; k++) {
          datearray[k] = selected[k].date
          datearray[k] = datearray[k].getFullYear() + datearray[k].getDate();
        }

        mousedate = datearray.indexOf(invertedx);
        pro = d.values[mousedate].value;

        d3.select(this)
        .classed("hover", true)
        .attr("stroke", strokecolor)
        .attr("stroke-width", "0.5px"),
        tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible");

      })
      .on("mouseout", function(d, i) {
       svg.selectAll(".layer")
        .transition()
        .duration(250)
        .attr("opacity", "1");
        d3.select(this)
        .classed("hover", false)
        .attr("stroke-width", "0px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden");
    })

    var vertical = d3.select(".chart")
          .append("div")
          .attr("class", "remove")
          .style("position", "absolute")
          .style("z-index", "19")
          .style("width", "1px")
          .style("height", "380px")
          .style("top", "10px")
          .style("bottom", "30px")
          .style("left", "0px")
          .style("background", "#fff");

    d3.select(".chart")
        .on("mousemove", function(){
           mousex = d3.mouse(this);
           mousex = mousex[0] + 5;
           vertical.style("left", mousex + "px" )})
        .on("mouseover", function(){
           mousex = d3.mouse(this);
           mousex = mousex[0] + 5;
           vertical.style("left", mousex + "px")});
  });
}
</script>

但是,我还需要像上图那样根据消耗量改变流的位置。我可以修改流布局来达到这个效果吗?还是我需要为此编写自定义布局?任何提示或想法都会有所帮助。

4

0 回答 0