【问题标题】:how to draw a grid incrementally in d3?如何在 d3 中逐步绘制网格?
【发布时间】:2018-12-31 18:49:31
【问题描述】:

下面是一个 HTML 文件,它会绘制一个 10x10 的正方形网格,由浅灰色和深灰色交替出现。它用 0 或 1 填充一个名为 the_grid 的二维数组;然后用xycolor 填充一个名为nodes 的一维数组;然后用 d3 绘制nodes。他们都出现了。它们看起来像这样:

我如何按照nodes 数组给出的顺序一次绘制(即出现)一个nodes(这样我就可以绘制不同的图案,比如垂直擦除、水平擦除等等)?

我尝试摆弄transition 函数但没有成功。它只是绘制整个网格,并将其滑入到位。方块并没有明显地一一出现。

代码:

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <script>
      function draw_function() {
          var vis = d3.select("#graph")
              .append("svg")
              .attr("width", 200).attr("height", 200);

          // fill the_grid
          var shape=[10,10];
          var the_grid=[];
          for (var idx = 0; idx < shape[0]; idx++) {
              var row = [];
              for (var jdx = 0; jdx < shape[1]; jdx++) {
                  var val = (idx+jdx)/2;
                  row.push(Math.floor(val)==val ? 1 : 0);
              }
              the_grid.push(row);
          }

          // fill nodes
          var rectwidth = 10;
          var nodes = [];
          for (var idx = 0; idx < the_grid.length; idx++) {
              for (var jdx = 0; jdx < the_grid[0].length; jdx++) {
                  var node = {x: idx * (rectwidth+1),
                              y: jdx * (rectwidth+1),
                              color: the_grid[idx][jdx] == 1 ? 'black' : 'lightgrey'};
                  nodes.push(node);
              }
          }

          // draw nodes
          vis.selectAll("rect.nodes")
              .data(nodes)
              .enter()
              .append("svg:rect")
              .attr("x", function(d) { return d.x; })
              .attr("y", function(d) { return d.y; })
              .attr("height", rectwidth)
              .attr("width", rectwidth)
              .attr("fill", function(d) { return d.color; })
      }

      // function has to execute after dom is loaded
      window.onload = draw_function
    </script>

    <style>rect { color: black; }</style>
  </head>

  <body><div id="graph"/></body>
</html>

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    要错开从同一数据数组中同时输入的多个元素的转换,您可以使用transition.delay(),您可以指定一个常量(它将同时启动所有转换),或者您可以指定一个函数来确定延迟在每个元素或其索引的基准上:

    selection.transition()
      .delay(function(d,i) { return i * 100; })
      .attr(...
    

    上面和下面的 sn-p 我都使用了索引:

    function draw_function() {
              var vis = d3.select("#graph")
                  .append("svg")
                  .attr("width", 200).attr("height", 200);
    
              // fill the_grid
              var shape=[10,10];
              var the_grid=[];
              for (var idx = 0; idx < shape[0]; idx++) {
                  var row = [];
                  for (var jdx = 0; jdx < shape[1]; jdx++) {
                      var val = (idx+jdx)/2;
                      row.push(Math.floor(val)==val ? 1 : 0);
                  }
                  the_grid.push(row);
              }
    
              // fill nodes
              var rectwidth = 10;
              var nodes = [];
              for (var idx = 0; idx < the_grid.length; idx++) {
                  for (var jdx = 0; jdx < the_grid[0].length; jdx++) {
                      var node = {x: idx * (rectwidth+1),
                                  y: jdx * (rectwidth+1),
                                  color: the_grid[idx][jdx] == 1 ? 'black' : 'lightgrey'};
                      nodes.push(node);
                  }
              }
    
              // draw nodes
              vis.selectAll("rect.nodes")
                  .data(nodes)
                  .enter()
                  .append("svg:rect")
                  .attr("x", function(d) { return d.x; })
                  .attr("y", function(d) { return d.y; })
                  .attr("height", rectwidth)
                  .attr("width", rectwidth)
                  .attr("fill","white")
                  .transition()
                  .duration(1000)
                  .delay(function(d,i) { return i * 100; })
                  .attr("fill", function(d) { return d.color; })
          }
    
          // function has to execute after dom is loaded
          window.onload = draw_function
    <html>
      <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <div id="graph"/>

    下面我使用了基准来创建一个随机的过渡顺序:

    function draw_function() {
              var vis = d3.select("#graph")
                  .append("svg")
                  .attr("width", 200).attr("height", 200);
    
              // fill the_grid
              var shape=[10,10];
              var the_grid=[];
              for (var idx = 0; idx < shape[0]; idx++) {
                  var row = [];
                  for (var jdx = 0; jdx < shape[1]; jdx++) {
                      var val = (idx+jdx)/2;
                      row.push(Math.floor(val)==val ? 1 : 0);
                  }
                  the_grid.push(row);
              }
    
              // fill nodes
              var rectwidth = 10;
              var nodes = [];
              for (var idx = 0; idx < the_grid.length; idx++) {
                  for (var jdx = 0; jdx < the_grid[0].length; jdx++) {
                      var node = {
                                  delay: Math.random()*2000,
                                  x: idx * (rectwidth+1),
                                  y: jdx * (rectwidth+1),
                                  color: the_grid[idx][jdx] == 1 ? 'black' : 'lightgrey'};
                      nodes.push(node);
                  }
              }
    
              // draw nodes
              vis.selectAll("rect.nodes")
                  .data(nodes)
                  .enter()
                  .append("svg:rect")
                  .attr("x", function(d) { return d.x; })
                  .attr("y", function(d) { return d.y; })
                  .attr("height", rectwidth)
                  .attr("width", rectwidth)
                  .attr("fill","white")
                  .transition()
                  .duration(1000)
                  .delay(function(d,i) { return d.delay; })
                  .attr("fill", function(d) { return d.color; })
          }
    
          // function has to execute after dom is loaded
          window.onload = draw_function
    <html>
      <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <div id="graph"/>

    【讨论】:

    • 太棒了!秘密似乎是“延迟”功能,并将其放在正确的位置。不需要持续时间。
    • 我使用持续时间只是为了稍微减慢过渡本身,但是是的,它不需要(但我搞砸了,我将初始填充设置为none,我已将其更新为white这样 d3 可以在开始值和结束值之间进行插值,而无需进一步修改){
    • 它会按nodes 的顺序绘制,还是我必须将延迟设置为正确的值才能按顺序显示它们?
    • 如果使用数据数组中节点的索引 (i * time),则转换将始终按照它们在数组中的顺序开始。
    猜你喜欢
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2013-02-10
    相关资源
    最近更新 更多