如何动态更新d3包

时间:2017-01-02 15:05:56

标签: javascript d3.js

我是D3的新手,我不明白它的所有逻辑。

我尝试使用示例,但它似乎有很多方法可以让我感到困惑......

无论如何,我试着让example动态。

以下是我现在的代码:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

text {
  font: 12px sans-serif;
  text-anchor: middle;
}
.titre {
    font-size: 18px;
}

.node--hover circle {
  stroke: #000;
  stroke-width: 1.2px;
}
#csv {
    float: left;
}
</style>
<form>
    <textarea name="csv" id="csv" cols="50" rows="30">id,taille,titre
D3,
D3.one,2000
D3.two,2000</textarea>
</form>
<svg width="400" height="400"><g transform="translate(1,1)"></g></svg>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

var format = d3.format(",d");

    var color = d3.scaleSequential(d3.interpolateMagma)
        .domain([-4, 4]);
    var stratify = d3.stratify()
        .parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });
    var pack = d3.pack()
        .size([width - 2, height - 2])
        .padding(3);

    var csv = $("#csv").val();

    data = d3.csvParse(csv);

      var root = stratify(data)
          .sum(function(d) { return d.taille; })
          .sort(function(a, b) { return b.taille - a.taille; });

      pack(root);

      var node = svg.select("g")
        .selectAll("g")
        .data(root.descendants())
        .enter().append("g")
          .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
          .attr("class", function(d) { return "node" + (!d.children ? " node--leaf" : d.depth ? "" : " node--root"); })
          .each(function(d) { d.node = this; });


      node.append("circle")
          .attr("id", function(d) { return "node-" + d.id; })
          .attr("r", function(d) { return d.r; })
          .style("fill", function(d) { 
              return color(d.depth); 
          });

      var leaf = node.filter(function(d) { return !d.children; });

      leaf.append("clipPath")
          .attr("id", function(d) { return "clip-" + d.id; })
        .append("use")
          .attr("xlink:href", function(d) { return "#node-" + d.id + ""; });

      leaf.append("text")
          .attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; }).attr("class", function(d) { return d.data.titre=="1" ? "titre" : ""})
        .selectAll("tspan")
        .data(function(d) { return d.id.substring(d.id.lastIndexOf(".") + 1).split(/(?=[A-Z][^A-Z])/g); })
        .enter().append("tspan")
          .attr("x", 0)
          .attr("y", function(d, i, nodes) { return 13 + (i - nodes.length / 2 - 0.5) * 20; })
          .text(function(d) { return d; });

$(function() {  
    $("#csv").blur(function()
    {
        update();
    });
});

function update()
{
    var csv = $("#csv").val();

    data = d3.csvParse(csv);

      var root = stratify(data)
          .sum(function(d) { return d.taille; })
          .sort(function(a, b) { return b.taille - a.taille; });

      pack(root);

    //console.log(root.descendants());
      node = node.data(root.descendants(), function(d) {return d});
      console.log(node);
      //node.exit().remove();
      node.enter().append("g")
          .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
          .attr("class", function(d) { return "node" + (!d.children ? " node--leaf" : d.depth ? "" : " node--root"); })
          .each(function(d) { d.node = this; });

      node.append("circle")
          .attr("id", function(d) { return "node-" + d.id; })
          .attr("r", function(d) { return d.r; })
          .style("fill", function(d) { 
              return color(d.depth); 
          });

      var leaf = node.filter(function(d) { return !d.children; });

      leaf.append("clipPath")
          .attr("id", function(d) { return "clip-" + d.id; })
        .append("use")
          .attr("xlink:href", function(d) { return "#node-" + d.id + ""; });

      leaf.append("text")
          .attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; }).attr("class", function(d) { return d.data.titre=="1" ? "titre" : ""})
        .selectAll("tspan")
        .data(function(d) { return d.id.substring(d.id.lastIndexOf(".") + 1).split(/(?=[A-Z][^A-Z])/g); })
        .enter().append("tspan")
          .attr("x", 0)
          .attr("y", function(d, i, nodes) { return 13 + (i - nodes.length / 2 - 0.5) * 20; })
          .text(function(d) { return d; });
}



</script>

你可以在bl.ocks上测试它: https://bl.ocks.org/matthieubrunet/79ef9968e2eaaba7f0718a373d240025

更新应该在模糊时发生。

我认为我的问题在于输入函数(在更新函数中),它返回所有元素而不是新元素。

正如你所看到的,我注释掉了退出,因为它删除了所有的孩子圈子。

非常感谢

1 个答案:

答案 0 :(得分:2)

d3最令人困惑的事情之一是如何处理enterupdateexit模式。我不会为您提供相关教程,因为那里有许多优秀的资源already - out但是我花时间重新考虑你的update函数来正确处理这些情况:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  text {
    font: 12px sans-serif;
    text-anchor: middle;
  }
  
  .titre {
    font-size: 18px;
  }
  
  .node--hover circle {
    stroke: #000;
    stroke-width: 1.2px;
  }
  
  #csv {
    float: left;
  }
</style>
<form>
<textarea name="csv" id="csv" cols="50" rows="30">id,taille,titre
D3,
D3.one,2000
D3.two,2000</textarea>
</form>
<svg width="400" height="400">
  <g transform="translate(1,1)"></g>
</svg>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
  var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

  var format = d3.format(",d");

  var color = d3.scaleSequential(d3.interpolateMagma)
    .domain([-4, 4]);
  var stratify = d3.stratify()
    .parentId(function(d) {
      return d.id.substring(0, d.id.lastIndexOf("."));
    });
  var pack = d3.pack()
    .size([width - 2, height - 2])
    .padding(3);

  update();

  $(function() {
    $("#csv").blur(function() {
      update();
    });
  });

  function update() {
    var csv = $("#csv").val();

    data = d3.csvParse(csv);

    var root = stratify(data)
      .sum(function(d) {
        return d.taille;
      })
      .sort(function(a, b) {
        return b.taille - a.taille;
      });

    pack(root);
    
    // data-binding
    var node = svg.selectAll(".node").data(root.descendants(), function(d){
      return d;
    });
    
    // exiting nodes
    node.exit().remove();

    // entering nodes
    var nodeEnter = node.enter().append("g")
      .attr("class", function(d) {
        return "node" + (!d.children ? " node--leaf" : d.depth ? "" : " node--root");
      });
      
    // add circles
    nodeEnter.append("circle")
      .attr("id", function(d) {
        return "node-" + d.id;
    });
    
    // update + enter
    node = nodeEnter.merge(node);
      
    // position everyone
    node.attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });
    
    // update circles
    node.select("circle")
      .attr("r", function(d) {
        return d.r;
      })
      .style("fill", function(d) {
        return color(d.depth);
      });
    
    // handle enter of leafs
    var leafEnter = nodeEnter.filter(function(d) {
      return !d.children;
    });
    
    leafEnter.append("clipPath")
      .attr("id", function(d) {
        return "clip-" + d.id;
      })
      .append("use")
      .attr("xlink:href", function(d) {
        return "#node-" + d.id + "";
      });
      
    leafEnter.append("text")
      .attr("clip-path", function(d) {
        return "url(#clip-" + d.id + ")";
      }).attr("class", function(d) {
        return d.data.titre == "1" ? "titre" : "";
      });

    node.select("text")
      .selectAll("tspan")
      .data(function(d) {
        return d.id.substring(d.id.lastIndexOf(".") + 1).split(/(?=[A-Z][^A-Z])/g);
      })
      .enter().append("tspan")
      .attr("x", 0)
      .attr("y", function(d, i, nodes) {
        return 13 + (i - nodes.length / 2 - 0.5) * 20;
      })
      .text(function(d) {
        return d;
      });
  }
</script>