如何在d3中增量绘制网格? [英] how to draw a grid incrementally in d3?

查看:81
本文介绍了如何在d3中增量绘制网格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一个HTML文件,该文件将绘制一个10x10的正方形网格,交替显示浅灰色和深灰色.它用0或1填充称为the_grid的2d数组;然后用xycolor填充一个名为nodes的一维数组;然后用d3绘制nodes.它们全部出现.他们看起来像这样:

我该如何按照nodes数组给出的顺序一次绘制(即出现)一个nodes(这样我就可以绘制不同的图案,例如垂直划像,水平划像等等)?/p>

我尝试摆弄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>

解决方案

要错开从同一数据数组中同时输入的多个元素的过渡,可以使用transition.delay(),可以指定一个常量(该常量将开始所有跃迁同时进行),也可以指定一个函数将延迟基于每个元素或其索引的基准:

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

上面和下面的代码段中,我使用了索引:

 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"/> 

Below is an HTML file that will draw a 10x10 grid of squares alternating light grey and dark grey. It fills a 2d array called the_grid with 0 or 1; then fills a 1d array called nodes with x, y, and color; then draws nodes with d3. They all appear. They look like this:

How do I instead have nodes drawn (i.e. appear) one at a time, in the order given by the nodes array (so I could draw different patterns, say vertical wipe, horizontal wipe, whatever)?

I tried fiddling with the transition function without success. It just draws the whole grid, and slides it into place. The squares don't visibly appear one by one.

The code:

<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>

解决方案

To stagger the transitions of multiple elements entered at the same time from the same data array you can use transition.delay(), you can specify a constant (which will start all transitions simutaneously) or you can specify a function to base the delay on the datum of each element or its index:

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

Above and in the snippet below I've used the index:

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"/>

And below I've used the datum to create a random transition order:

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"/>

这篇关于如何在d3中增量绘制网格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆